hs-uix 2.1.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/calendar.js +61 -81
- package/dist/calendar.mjs +62 -81
- package/dist/index.js +61 -80
- package/dist/index.mjs +62 -80
- package/package.json +1 -1
- package/src/calendar/README.md +2 -0
- package/src/calendar/index.d.ts +13 -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
|
|
@@ -1211,21 +1210,6 @@ var formatTimeZoneLabel = (tz, atDate = /* @__PURE__ */ new Date()) => {
|
|
|
1211
1210
|
|
|
1212
1211
|
// src/calendar/svgChips.js
|
|
1213
1212
|
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
1213
|
var DOT_FILL = {
|
|
1230
1214
|
default: "#7C98B6",
|
|
1231
1215
|
info: "#00A4BD",
|
|
@@ -1240,23 +1224,6 @@ var makeDotDataUri = (variant = "default", size = 8) => {
|
|
|
1240
1224
|
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
1225
|
return { src: toDataUri(svg), width: size, height: size };
|
|
1242
1226
|
};
|
|
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
1227
|
var makeSpacerDataUri = (height = 24, width = 4) => {
|
|
1261
1228
|
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
1229
|
return { src: toDataUri(svg), width, height };
|
|
@@ -1352,6 +1319,24 @@ var STATUS_VARIANT = {
|
|
|
1352
1319
|
error: "danger",
|
|
1353
1320
|
danger: "danger"
|
|
1354
1321
|
};
|
|
1322
|
+
var TAG_VARIANT = {
|
|
1323
|
+
default: "default",
|
|
1324
|
+
info: "info",
|
|
1325
|
+
success: "success",
|
|
1326
|
+
warning: "warning",
|
|
1327
|
+
error: "error",
|
|
1328
|
+
danger: "error"
|
|
1329
|
+
};
|
|
1330
|
+
var MONTH_EVENT_STYLES = /* @__PURE__ */ new Set(["statusTag", "tag"]);
|
|
1331
|
+
var monthLabelMaxChars = (style) => {
|
|
1332
|
+
const overhead = style === "tag" ? 34 : 46;
|
|
1333
|
+
return Math.max(6, Math.floor((MONTH_COL_WIDTH - overhead) / 6.6));
|
|
1334
|
+
};
|
|
1335
|
+
var truncateMonthLabel = (value, max) => {
|
|
1336
|
+
const s = String(value == null ? "" : value);
|
|
1337
|
+
if (!max || s.length <= max) return s;
|
|
1338
|
+
return s.slice(0, max).trimEnd();
|
|
1339
|
+
};
|
|
1355
1340
|
var MONTH_COL_WIDTH = 160;
|
|
1356
1341
|
var TIMEGRID_DAY_COL = 150;
|
|
1357
1342
|
var TIMEGRID_DAY_COL_SINGLE = 560;
|
|
@@ -1370,7 +1355,7 @@ var EventDetail = ({ event, labels }) => {
|
|
|
1370
1355
|
when = `${formatDayTitle(start)} \u2013 ${formatDayTitle(end)}`;
|
|
1371
1356
|
}
|
|
1372
1357
|
}
|
|
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,
|
|
1358
|
+
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);
|
|
1374
1359
|
};
|
|
1375
1360
|
var buildOverlay = (event, mode, renderEventDetail, labels, idSuffix = "") => {
|
|
1376
1361
|
if (mode === "none") return void 0;
|
|
@@ -1382,7 +1367,7 @@ var buildOverlay = (event, mode, renderEventDetail, labels, idSuffix = "") => {
|
|
|
1382
1367
|
if (mode === "panel") {
|
|
1383
1368
|
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
1369
|
}
|
|
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));
|
|
1370
|
+
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
1371
|
};
|
|
1387
1372
|
var AgendaEventRow = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels }) => {
|
|
1388
1373
|
const variant = VALID_VARIANTS.has(event.color) ? event.color : "default";
|
|
@@ -1391,9 +1376,8 @@ var AgendaEventRow = ({ event, day, overlayMode, renderEventDetail, onEventClick
|
|
|
1391
1376
|
const timeLabel = isAllDayEvent(event) ? labels.allDay : formatTime(event.start);
|
|
1392
1377
|
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
1378
|
};
|
|
1394
|
-
var
|
|
1395
|
-
var
|
|
1396
|
-
var MonthChip = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels }) => {
|
|
1379
|
+
var MONTH_SLOT_HEIGHT = 24;
|
|
1380
|
+
var MonthChip = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels, monthEventStyle, monthEventMaxChars }) => {
|
|
1397
1381
|
const isStartDay = !day || !event.start || isSameDay(event.start, day);
|
|
1398
1382
|
const overlay = buildOverlay(event, overlayMode, renderEventDetail, labels, day ? `-m${day.getTime()}` : "");
|
|
1399
1383
|
const handleClick = onEventClick ? () => onEventClick(event.raw, event) : void 0;
|
|
@@ -1401,23 +1385,12 @@ var MonthChip = ({ event, day, overlayMode, renderEventDetail, onEventClick, lab
|
|
|
1401
1385
|
const startHasTime = event.start && (event.start.getHours() !== 0 || event.start.getMinutes() !== 0);
|
|
1402
1386
|
const time = isStartDay && startHasTime ? `${formatTime(event.start)} ` : "";
|
|
1403
1387
|
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
|
-
);
|
|
1388
|
+
const maxChars = monthEventMaxChars != null ? monthEventMaxChars : monthLabelMaxChars(monthEventStyle);
|
|
1389
|
+
const label = truncateMonthLabel(`${prefix}${time}${event.title || "--"}`, maxChars);
|
|
1390
|
+
if (monthEventStyle === "tag") {
|
|
1391
|
+
return /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Tag, { variant: TAG_VARIANT[variant] || "default", overlay, onClick: handleClick }, label);
|
|
1392
|
+
}
|
|
1393
|
+
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
1394
|
};
|
|
1422
1395
|
var DayListItem = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels }) => {
|
|
1423
1396
|
const handleClick = onEventClick ? () => onEventClick(event.raw, event) : void 0;
|
|
@@ -1500,7 +1473,7 @@ var MonthView = ({
|
|
|
1500
1473
|
}) => {
|
|
1501
1474
|
const headers = weekdayLabels(weekStartsOn, hideWeekends, true);
|
|
1502
1475
|
const today = now || /* @__PURE__ */ new Date();
|
|
1503
|
-
const
|
|
1476
|
+
const slotSpacer = makeSpacerDataUri(MONTH_SLOT_HEIGHT, 1);
|
|
1504
1477
|
const renderCell = (day) => {
|
|
1505
1478
|
const dayEvents = eventsForDay(day);
|
|
1506
1479
|
const inMonth = isSameMonth(day, refDate);
|
|
@@ -1508,41 +1481,35 @@ var MonthView = ({
|
|
|
1508
1481
|
if (renderDayCell) return renderDayCell(day, dayEvents);
|
|
1509
1482
|
const shown = dayEvents.slice(0, maxEventsPerDay);
|
|
1510
1483
|
const hasOverflow = dayEvents.length > maxEventsPerDay;
|
|
1484
|
+
const heightSpacer = /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Image, { src: slotSpacer.src, width: slotSpacer.width, height: slotSpacer.height, alt: "" });
|
|
1485
|
+
const slotRow = (key, content) => /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Flex, { key, direction: "row", align: "center", gap: "flush" }, heightSpacer, content);
|
|
1511
1486
|
const slots = [];
|
|
1512
1487
|
for (let i = 0; i < maxEventsPerDay; i++) {
|
|
1513
1488
|
if (i < shown.length) {
|
|
1514
|
-
slots.push(/* @__PURE__ */ import_react5.default.createElement(MonthChip, {
|
|
1489
|
+
slots.push(slotRow(shown[i].key, /* @__PURE__ */ import_react5.default.createElement(MonthChip, { event: shown[i], day, ...chipProps })));
|
|
1515
1490
|
} else {
|
|
1516
|
-
slots.push(
|
|
1517
|
-
/* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Image, { key: `sp-${i}`, src: spacer24.src, width: spacer24.width, height: spacer24.height, alt: "" })
|
|
1518
|
-
);
|
|
1491
|
+
slots.push(/* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Image, { key: `sp-${i}`, src: slotSpacer.src, width: slotSpacer.width, height: slotSpacer.height, alt: "" }));
|
|
1519
1492
|
}
|
|
1520
1493
|
}
|
|
1521
1494
|
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
1495
|
slots.push(
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
}
|
|
1496
|
+
slotRow(
|
|
1497
|
+
"more",
|
|
1498
|
+
/* @__PURE__ */ import_react5.default.createElement(
|
|
1499
|
+
import_ui_extensions5.Link,
|
|
1500
|
+
{
|
|
1501
|
+
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", justify: "center", align: "center", gap: "xs" }, /* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Text, { format: { fontWeight: "bold" } }, 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)))))
|
|
1502
|
+
},
|
|
1503
|
+
labels.more(dayEvents.length - maxEventsPerDay)
|
|
1504
|
+
)
|
|
1538
1505
|
)
|
|
1539
1506
|
);
|
|
1540
1507
|
} else {
|
|
1541
1508
|
slots.push(
|
|
1542
|
-
/* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Image, { key: "more-sp", src:
|
|
1509
|
+
/* @__PURE__ */ import_react5.default.createElement(import_ui_extensions5.Image, { key: "more-sp", src: slotSpacer.src, width: slotSpacer.width, height: slotSpacer.height, alt: "" })
|
|
1543
1510
|
);
|
|
1544
1511
|
}
|
|
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);
|
|
1512
|
+
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()))), slots));
|
|
1546
1513
|
};
|
|
1547
1514
|
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
1515
|
const days = hideWeekends ? week.filter((d) => d.getDay() !== 0 && d.getDay() !== 6) : week;
|
|
@@ -1585,6 +1552,7 @@ var TimeGridView = ({ days, now, hours, dayStartHour, dayEndHour, eventsForDay,
|
|
|
1585
1552
|
const today = now || /* @__PURE__ */ new Date();
|
|
1586
1553
|
const centerDays = days.length === 1;
|
|
1587
1554
|
const dayColWidth = days.length === 1 ? TIMEGRID_DAY_COL_SINGLE : TIMEGRID_DAY_COL;
|
|
1555
|
+
const weekTitleMaxChars = Math.max(6, Math.floor((TIMEGRID_DAY_COL - 46) / 6.6));
|
|
1588
1556
|
const todayInView = days.some((d) => isSameDay(d, today));
|
|
1589
1557
|
const nowHour = today.getHours();
|
|
1590
1558
|
const dayData = days.map((day) => {
|
|
@@ -1629,10 +1597,10 @@ var TimeGridView = ({ days, now, hours, dayStartHour, dayEndHour, eventsForDay,
|
|
|
1629
1597
|
} else if (mode === "cont") {
|
|
1630
1598
|
sub = `\u2191 cont. through ${endLabel}`;
|
|
1631
1599
|
}
|
|
1632
|
-
|
|
1600
|
+
const titleLabel = centerDays ? e.title || "--" : truncateMonthLabel(e.title || "--", weekTitleMaxChars);
|
|
1601
|
+
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
1602
|
};
|
|
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: "" })));
|
|
1603
|
+
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
1604
|
const slotSpacer = makeSpacerDataUri(HOUR_SLOT_HEIGHT, 1);
|
|
1637
1605
|
const emptyCell = null;
|
|
1638
1606
|
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,6 +1656,10 @@ var Calendar = (props) => {
|
|
|
1688
1656
|
weekStartsOn = 0,
|
|
1689
1657
|
hideWeekends = false,
|
|
1690
1658
|
maxEventsPerDay = DEFAULT_MAX_EVENTS_PER_DAY,
|
|
1659
|
+
// month-grid event token style: "statusTag" (dot + text, default) | "tag" (pill)
|
|
1660
|
+
monthEventStyle = "statusTag",
|
|
1661
|
+
// max characters for a month-cell label before "…" (default derived per style)
|
|
1662
|
+
monthEventMaxChars,
|
|
1691
1663
|
// time grid (week / day)
|
|
1692
1664
|
dayStartHour = DEFAULT_DAY_START_HOUR,
|
|
1693
1665
|
dayEndHour = DEFAULT_DAY_END_HOUR,
|
|
@@ -1907,7 +1879,15 @@ var Calendar = (props) => {
|
|
|
1907
1879
|
}
|
|
1908
1880
|
return formatMonthTitle(focusedDate);
|
|
1909
1881
|
}, [view, focusedDate, weekStartsOn, hideWeekends]);
|
|
1910
|
-
const
|
|
1882
|
+
const safeMonthEventStyle = MONTH_EVENT_STYLES.has(monthEventStyle) ? monthEventStyle : "statusTag";
|
|
1883
|
+
const chipProps = {
|
|
1884
|
+
overlayMode,
|
|
1885
|
+
renderEventDetail,
|
|
1886
|
+
onEventClick,
|
|
1887
|
+
labels,
|
|
1888
|
+
monthEventStyle: safeMonthEventStyle,
|
|
1889
|
+
monthEventMaxChars
|
|
1890
|
+
};
|
|
1911
1891
|
const timeZoneOptions = (0, import_react5.useMemo)(() => {
|
|
1912
1892
|
if (!showTimeZoneSelect) return null;
|
|
1913
1893
|
const base = (timeZoneOptionsProp && timeZoneOptionsProp.length ? timeZoneOptionsProp : DEFAULT_TIME_ZONES).map(
|
package/dist/calendar.mjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
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,
|
|
7
8
|
Divider,
|
|
@@ -91,7 +92,6 @@ import React2 from "react";
|
|
|
91
92
|
import { Image, Icon as HsIcon, Link } from "@hubspot/ui-extensions";
|
|
92
93
|
|
|
93
94
|
// src/common-components/svgDefaults.js
|
|
94
|
-
var HS_FONT_FAMILY = '"Lexend Deca", Helvetica, Arial, sans-serif';
|
|
95
95
|
var HS_TEXT_COLOR = "#33475b";
|
|
96
96
|
|
|
97
97
|
// src/common-components/icons.generated.js
|
|
@@ -1213,21 +1213,6 @@ var formatTimeZoneLabel = (tz, atDate = /* @__PURE__ */ new Date()) => {
|
|
|
1213
1213
|
|
|
1214
1214
|
// src/calendar/svgChips.js
|
|
1215
1215
|
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
1216
|
var DOT_FILL = {
|
|
1232
1217
|
default: "#7C98B6",
|
|
1233
1218
|
info: "#00A4BD",
|
|
@@ -1242,23 +1227,6 @@ var makeDotDataUri = (variant = "default", size = 8) => {
|
|
|
1242
1227
|
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
1228
|
return { src: toDataUri(svg), width: size, height: size };
|
|
1244
1229
|
};
|
|
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
1230
|
var makeSpacerDataUri = (height = 24, width = 4) => {
|
|
1263
1231
|
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
1232
|
return { src: toDataUri(svg), width, height };
|
|
@@ -1354,6 +1322,24 @@ var STATUS_VARIANT = {
|
|
|
1354
1322
|
error: "danger",
|
|
1355
1323
|
danger: "danger"
|
|
1356
1324
|
};
|
|
1325
|
+
var TAG_VARIANT = {
|
|
1326
|
+
default: "default",
|
|
1327
|
+
info: "info",
|
|
1328
|
+
success: "success",
|
|
1329
|
+
warning: "warning",
|
|
1330
|
+
error: "error",
|
|
1331
|
+
danger: "error"
|
|
1332
|
+
};
|
|
1333
|
+
var MONTH_EVENT_STYLES = /* @__PURE__ */ new Set(["statusTag", "tag"]);
|
|
1334
|
+
var monthLabelMaxChars = (style) => {
|
|
1335
|
+
const overhead = style === "tag" ? 34 : 46;
|
|
1336
|
+
return Math.max(6, Math.floor((MONTH_COL_WIDTH - overhead) / 6.6));
|
|
1337
|
+
};
|
|
1338
|
+
var truncateMonthLabel = (value, max) => {
|
|
1339
|
+
const s = String(value == null ? "" : value);
|
|
1340
|
+
if (!max || s.length <= max) return s;
|
|
1341
|
+
return s.slice(0, max).trimEnd();
|
|
1342
|
+
};
|
|
1357
1343
|
var MONTH_COL_WIDTH = 160;
|
|
1358
1344
|
var TIMEGRID_DAY_COL = 150;
|
|
1359
1345
|
var TIMEGRID_DAY_COL_SINGLE = 560;
|
|
@@ -1372,7 +1358,7 @@ var EventDetail = ({ event, labels }) => {
|
|
|
1372
1358
|
when = `${formatDayTitle(start)} \u2013 ${formatDayTitle(end)}`;
|
|
1373
1359
|
}
|
|
1374
1360
|
}
|
|
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,
|
|
1361
|
+
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);
|
|
1376
1362
|
};
|
|
1377
1363
|
var buildOverlay = (event, mode, renderEventDetail, labels, idSuffix = "") => {
|
|
1378
1364
|
if (mode === "none") return void 0;
|
|
@@ -1384,7 +1370,7 @@ var buildOverlay = (event, mode, renderEventDetail, labels, idSuffix = "") => {
|
|
|
1384
1370
|
if (mode === "panel") {
|
|
1385
1371
|
return /* @__PURE__ */ React5.createElement(Panel, { id, title: event.title || labels.open, width: "small", variant: "modal" }, /* @__PURE__ */ React5.createElement(PanelBody, null, body));
|
|
1386
1372
|
}
|
|
1387
|
-
return /* @__PURE__ */ React5.createElement(Popover, { id, placement: "bottom" }, /* @__PURE__ */ React5.createElement(Tile, { compact: true }, body));
|
|
1373
|
+
return /* @__PURE__ */ React5.createElement(Popover, { id, placement: "bottom", variant: "longform" }, /* @__PURE__ */ React5.createElement(Tile, { compact: true }, body));
|
|
1388
1374
|
};
|
|
1389
1375
|
var AgendaEventRow = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels }) => {
|
|
1390
1376
|
const variant = VALID_VARIANTS.has(event.color) ? event.color : "default";
|
|
@@ -1393,9 +1379,8 @@ var AgendaEventRow = ({ event, day, overlayMode, renderEventDetail, onEventClick
|
|
|
1393
1379
|
const timeLabel = isAllDayEvent(event) ? labels.allDay : formatTime(event.start);
|
|
1394
1380
|
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
1381
|
};
|
|
1396
|
-
var
|
|
1397
|
-
var
|
|
1398
|
-
var MonthChip = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels }) => {
|
|
1382
|
+
var MONTH_SLOT_HEIGHT = 24;
|
|
1383
|
+
var MonthChip = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels, monthEventStyle, monthEventMaxChars }) => {
|
|
1399
1384
|
const isStartDay = !day || !event.start || isSameDay(event.start, day);
|
|
1400
1385
|
const overlay = buildOverlay(event, overlayMode, renderEventDetail, labels, day ? `-m${day.getTime()}` : "");
|
|
1401
1386
|
const handleClick = onEventClick ? () => onEventClick(event.raw, event) : void 0;
|
|
@@ -1403,23 +1388,12 @@ var MonthChip = ({ event, day, overlayMode, renderEventDetail, onEventClick, lab
|
|
|
1403
1388
|
const startHasTime = event.start && (event.start.getHours() !== 0 || event.start.getMinutes() !== 0);
|
|
1404
1389
|
const time = isStartDay && startHasTime ? `${formatTime(event.start)} ` : "";
|
|
1405
1390
|
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
|
-
);
|
|
1391
|
+
const maxChars = monthEventMaxChars != null ? monthEventMaxChars : monthLabelMaxChars(monthEventStyle);
|
|
1392
|
+
const label = truncateMonthLabel(`${prefix}${time}${event.title || "--"}`, maxChars);
|
|
1393
|
+
if (monthEventStyle === "tag") {
|
|
1394
|
+
return /* @__PURE__ */ React5.createElement(Tag2, { variant: TAG_VARIANT[variant] || "default", overlay, onClick: handleClick }, label);
|
|
1395
|
+
}
|
|
1396
|
+
return /* @__PURE__ */ React5.createElement(Link2, { overlay, onClick: handleClick }, /* @__PURE__ */ React5.createElement(StatusTag, { variant: STATUS_VARIANT[variant] || "default" }, label));
|
|
1423
1397
|
};
|
|
1424
1398
|
var DayListItem = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels }) => {
|
|
1425
1399
|
const handleClick = onEventClick ? () => onEventClick(event.raw, event) : void 0;
|
|
@@ -1502,7 +1476,7 @@ var MonthView = ({
|
|
|
1502
1476
|
}) => {
|
|
1503
1477
|
const headers = weekdayLabels(weekStartsOn, hideWeekends, true);
|
|
1504
1478
|
const today = now || /* @__PURE__ */ new Date();
|
|
1505
|
-
const
|
|
1479
|
+
const slotSpacer = makeSpacerDataUri(MONTH_SLOT_HEIGHT, 1);
|
|
1506
1480
|
const renderCell = (day) => {
|
|
1507
1481
|
const dayEvents = eventsForDay(day);
|
|
1508
1482
|
const inMonth = isSameMonth(day, refDate);
|
|
@@ -1510,41 +1484,35 @@ var MonthView = ({
|
|
|
1510
1484
|
if (renderDayCell) return renderDayCell(day, dayEvents);
|
|
1511
1485
|
const shown = dayEvents.slice(0, maxEventsPerDay);
|
|
1512
1486
|
const hasOverflow = dayEvents.length > maxEventsPerDay;
|
|
1487
|
+
const heightSpacer = /* @__PURE__ */ React5.createElement(Image2, { src: slotSpacer.src, width: slotSpacer.width, height: slotSpacer.height, alt: "" });
|
|
1488
|
+
const slotRow = (key, content) => /* @__PURE__ */ React5.createElement(Flex4, { key, direction: "row", align: "center", gap: "flush" }, heightSpacer, content);
|
|
1513
1489
|
const slots = [];
|
|
1514
1490
|
for (let i = 0; i < maxEventsPerDay; i++) {
|
|
1515
1491
|
if (i < shown.length) {
|
|
1516
|
-
slots.push(/* @__PURE__ */ React5.createElement(MonthChip, {
|
|
1492
|
+
slots.push(slotRow(shown[i].key, /* @__PURE__ */ React5.createElement(MonthChip, { event: shown[i], day, ...chipProps })));
|
|
1517
1493
|
} else {
|
|
1518
|
-
slots.push(
|
|
1519
|
-
/* @__PURE__ */ React5.createElement(Image2, { key: `sp-${i}`, src: spacer24.src, width: spacer24.width, height: spacer24.height, alt: "" })
|
|
1520
|
-
);
|
|
1494
|
+
slots.push(/* @__PURE__ */ React5.createElement(Image2, { key: `sp-${i}`, src: slotSpacer.src, width: slotSpacer.width, height: slotSpacer.height, alt: "" }));
|
|
1521
1495
|
}
|
|
1522
1496
|
}
|
|
1523
1497
|
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
1498
|
slots.push(
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
}
|
|
1499
|
+
slotRow(
|
|
1500
|
+
"more",
|
|
1501
|
+
/* @__PURE__ */ React5.createElement(
|
|
1502
|
+
Link2,
|
|
1503
|
+
{
|
|
1504
|
+
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", justify: "center", align: "center", gap: "xs" }, /* @__PURE__ */ React5.createElement(Text, { format: { fontWeight: "bold" } }, 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)))))
|
|
1505
|
+
},
|
|
1506
|
+
labels.more(dayEvents.length - maxEventsPerDay)
|
|
1507
|
+
)
|
|
1540
1508
|
)
|
|
1541
1509
|
);
|
|
1542
1510
|
} else {
|
|
1543
1511
|
slots.push(
|
|
1544
|
-
/* @__PURE__ */ React5.createElement(Image2, { key: "more-sp", src:
|
|
1512
|
+
/* @__PURE__ */ React5.createElement(Image2, { key: "more-sp", src: slotSpacer.src, width: slotSpacer.width, height: slotSpacer.height, alt: "" })
|
|
1545
1513
|
);
|
|
1546
1514
|
}
|
|
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);
|
|
1515
|
+
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()))), slots));
|
|
1548
1516
|
};
|
|
1549
1517
|
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
1518
|
const days = hideWeekends ? week.filter((d) => d.getDay() !== 0 && d.getDay() !== 6) : week;
|
|
@@ -1587,6 +1555,7 @@ var TimeGridView = ({ days, now, hours, dayStartHour, dayEndHour, eventsForDay,
|
|
|
1587
1555
|
const today = now || /* @__PURE__ */ new Date();
|
|
1588
1556
|
const centerDays = days.length === 1;
|
|
1589
1557
|
const dayColWidth = days.length === 1 ? TIMEGRID_DAY_COL_SINGLE : TIMEGRID_DAY_COL;
|
|
1558
|
+
const weekTitleMaxChars = Math.max(6, Math.floor((TIMEGRID_DAY_COL - 46) / 6.6));
|
|
1590
1559
|
const todayInView = days.some((d) => isSameDay(d, today));
|
|
1591
1560
|
const nowHour = today.getHours();
|
|
1592
1561
|
const dayData = days.map((day) => {
|
|
@@ -1631,10 +1600,10 @@ var TimeGridView = ({ days, now, hours, dayStartHour, dayEndHour, eventsForDay,
|
|
|
1631
1600
|
} else if (mode === "cont") {
|
|
1632
1601
|
sub = `\u2191 cont. through ${endLabel}`;
|
|
1633
1602
|
}
|
|
1634
|
-
|
|
1603
|
+
const titleLabel = centerDays ? e.title || "--" : truncateMonthLabel(e.title || "--", weekTitleMaxChars);
|
|
1604
|
+
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
1605
|
};
|
|
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: "" })));
|
|
1606
|
+
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
1607
|
const slotSpacer = makeSpacerDataUri(HOUR_SLOT_HEIGHT, 1);
|
|
1639
1608
|
const emptyCell = null;
|
|
1640
1609
|
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,6 +1659,10 @@ var Calendar = (props) => {
|
|
|
1690
1659
|
weekStartsOn = 0,
|
|
1691
1660
|
hideWeekends = false,
|
|
1692
1661
|
maxEventsPerDay = DEFAULT_MAX_EVENTS_PER_DAY,
|
|
1662
|
+
// month-grid event token style: "statusTag" (dot + text, default) | "tag" (pill)
|
|
1663
|
+
monthEventStyle = "statusTag",
|
|
1664
|
+
// max characters for a month-cell label before "…" (default derived per style)
|
|
1665
|
+
monthEventMaxChars,
|
|
1693
1666
|
// time grid (week / day)
|
|
1694
1667
|
dayStartHour = DEFAULT_DAY_START_HOUR,
|
|
1695
1668
|
dayEndHour = DEFAULT_DAY_END_HOUR,
|
|
@@ -1909,7 +1882,15 @@ var Calendar = (props) => {
|
|
|
1909
1882
|
}
|
|
1910
1883
|
return formatMonthTitle(focusedDate);
|
|
1911
1884
|
}, [view, focusedDate, weekStartsOn, hideWeekends]);
|
|
1912
|
-
const
|
|
1885
|
+
const safeMonthEventStyle = MONTH_EVENT_STYLES.has(monthEventStyle) ? monthEventStyle : "statusTag";
|
|
1886
|
+
const chipProps = {
|
|
1887
|
+
overlayMode,
|
|
1888
|
+
renderEventDetail,
|
|
1889
|
+
onEventClick,
|
|
1890
|
+
labels,
|
|
1891
|
+
monthEventStyle: safeMonthEventStyle,
|
|
1892
|
+
monthEventMaxChars
|
|
1893
|
+
};
|
|
1913
1894
|
const timeZoneOptions = useMemo(() => {
|
|
1914
1895
|
if (!showTimeZoneSelect) return null;
|
|
1915
1896
|
const base = (timeZoneOptionsProp && timeZoneOptionsProp.length ? timeZoneOptionsProp : DEFAULT_TIME_ZONES).map(
|
package/dist/index.js
CHANGED
|
@@ -6957,21 +6957,6 @@ var formatTimeZoneLabel = (tz, atDate = /* @__PURE__ */ new Date()) => {
|
|
|
6957
6957
|
|
|
6958
6958
|
// src/calendar/svgChips.js
|
|
6959
6959
|
var toDataUri = (svg) => `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
|
6960
|
-
var escapeXml = (s) => String(s == null ? "" : s).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
6961
|
-
var truncateLabel = (value, max) => {
|
|
6962
|
-
const s = String(value == null ? "" : value);
|
|
6963
|
-
if (!max || s.length <= max) return s;
|
|
6964
|
-
return s.slice(0, Math.max(1, max - 1)).trimEnd() + "\u2026";
|
|
6965
|
-
};
|
|
6966
|
-
var CHIP_PALETTE = {
|
|
6967
|
-
default: { fill: "#7FD1DE", text: HS_TEXT_COLOR },
|
|
6968
|
-
info: { fill: "#00A4BD", text: "#FFFFFF" },
|
|
6969
|
-
success: { fill: "#00BDA5", text: "#FFFFFF" },
|
|
6970
|
-
warning: { fill: "#F5C26B", text: HS_TEXT_COLOR },
|
|
6971
|
-
error: { fill: "#F2545B", text: "#FFFFFF" },
|
|
6972
|
-
danger: { fill: "#F2545B", text: "#FFFFFF" }
|
|
6973
|
-
// StatusTag spells red "danger"; accept both
|
|
6974
|
-
};
|
|
6975
6960
|
var DOT_FILL = {
|
|
6976
6961
|
default: "#7C98B6",
|
|
6977
6962
|
info: "#00A4BD",
|
|
@@ -6986,23 +6971,6 @@ var makeDotDataUri = (variant = "default", size = 8) => {
|
|
|
6986
6971
|
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>`;
|
|
6987
6972
|
return { src: toDataUri(svg), width: size, height: size };
|
|
6988
6973
|
};
|
|
6989
|
-
var makeEventChipDataUri = (opts) => {
|
|
6990
|
-
const { label, width, height = 24, variant = "default" } = opts;
|
|
6991
|
-
const palette = CHIP_PALETTE[variant] || CHIP_PALETTE.default;
|
|
6992
|
-
const accentX = 5;
|
|
6993
|
-
const accentW = 3;
|
|
6994
|
-
const textX = accentX + accentW + 6;
|
|
6995
|
-
const rightPad = 8;
|
|
6996
|
-
const maxChars = Math.max(1, Math.floor((width - textX - rightPad) / 6));
|
|
6997
|
-
const text = truncateLabel(label, maxChars);
|
|
6998
|
-
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>`;
|
|
6999
|
-
return { src: toDataUri(svg), width, height };
|
|
7000
|
-
};
|
|
7001
|
-
var makeMoreDataUri = (opts) => {
|
|
7002
|
-
const { label, width, height = 24 } = opts;
|
|
7003
|
-
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>`;
|
|
7004
|
-
return { src: toDataUri(svg), width, height };
|
|
7005
|
-
};
|
|
7006
6974
|
var makeSpacerDataUri = (height = 24, width = 4) => {
|
|
7007
6975
|
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>`;
|
|
7008
6976
|
return { src: toDataUri(svg), width, height };
|
|
@@ -7098,6 +7066,24 @@ var STATUS_VARIANT = {
|
|
|
7098
7066
|
error: "danger",
|
|
7099
7067
|
danger: "danger"
|
|
7100
7068
|
};
|
|
7069
|
+
var TAG_VARIANT = {
|
|
7070
|
+
default: "default",
|
|
7071
|
+
info: "info",
|
|
7072
|
+
success: "success",
|
|
7073
|
+
warning: "warning",
|
|
7074
|
+
error: "error",
|
|
7075
|
+
danger: "error"
|
|
7076
|
+
};
|
|
7077
|
+
var MONTH_EVENT_STYLES = /* @__PURE__ */ new Set(["statusTag", "tag"]);
|
|
7078
|
+
var monthLabelMaxChars = (style) => {
|
|
7079
|
+
const overhead = style === "tag" ? 34 : 46;
|
|
7080
|
+
return Math.max(6, Math.floor((MONTH_COL_WIDTH - overhead) / 6.6));
|
|
7081
|
+
};
|
|
7082
|
+
var truncateMonthLabel = (value, max) => {
|
|
7083
|
+
const s = String(value == null ? "" : value);
|
|
7084
|
+
if (!max || s.length <= max) return s;
|
|
7085
|
+
return s.slice(0, max).trimEnd();
|
|
7086
|
+
};
|
|
7101
7087
|
var MONTH_COL_WIDTH = 160;
|
|
7102
7088
|
var TIMEGRID_DAY_COL = 150;
|
|
7103
7089
|
var TIMEGRID_DAY_COL_SINGLE = 560;
|
|
@@ -7116,7 +7102,7 @@ var EventDetail = ({ event, labels }) => {
|
|
|
7116
7102
|
when = `${formatDayTitle(start)} \u2013 ${formatDayTitle(end)}`;
|
|
7117
7103
|
}
|
|
7118
7104
|
}
|
|
7119
|
-
return /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Text, { format: { fontWeight: "demibold" } }, title || "--"), when ? /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Text, { variant: "microcopy" }, when) : null, subtitle ? /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Text,
|
|
7105
|
+
return /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Text, { format: { fontWeight: "demibold" }, truncate: true }, title || "--"), when ? /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Text, { variant: "microcopy", truncate: true }, when) : null, subtitle ? /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Text, { truncate: true }, subtitle) : null, href ? /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Link, { href: href.url, external: href.external }, labels.open) : null);
|
|
7120
7106
|
};
|
|
7121
7107
|
var buildOverlay = (event, mode, renderEventDetail, labels, idSuffix = "") => {
|
|
7122
7108
|
if (mode === "none") return void 0;
|
|
@@ -7128,7 +7114,7 @@ var buildOverlay = (event, mode, renderEventDetail, labels, idSuffix = "") => {
|
|
|
7128
7114
|
if (mode === "panel") {
|
|
7129
7115
|
return /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Panel, { id, title: event.title || labels.open, width: "small", variant: "modal" }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.PanelBody, null, body));
|
|
7130
7116
|
}
|
|
7131
|
-
return /* @__PURE__ */ import_react15.default.createElement(import_experimental.Popover, { id, placement: "bottom" }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Tile, { compact: true }, body));
|
|
7117
|
+
return /* @__PURE__ */ import_react15.default.createElement(import_experimental.Popover, { id, placement: "bottom", variant: "longform" }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Tile, { compact: true }, body));
|
|
7132
7118
|
};
|
|
7133
7119
|
var AgendaEventRow = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels }) => {
|
|
7134
7120
|
const variant = VALID_VARIANTS.has(event.color) ? event.color : "default";
|
|
@@ -7137,9 +7123,8 @@ var AgendaEventRow = ({ event, day, overlayMode, renderEventDetail, onEventClick
|
|
|
7137
7123
|
const timeLabel = isAllDayEvent(event) ? labels.allDay : formatTime(event.start);
|
|
7138
7124
|
return /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Flex, { direction: "row", align: "center", gap: "sm" }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Box, { flex: 2 }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Flex, { direction: "row", align: "center" }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Text, { variant: "microcopy", format: { fontWeight: "demibold" } }, timeLabel))), /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Box, { flex: 11 }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Flex, { direction: "row", align: "center", gap: "xs" }, /* @__PURE__ */ import_react15.default.createElement(ColorDot, { variant }), /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Text, { truncate: true }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Link, { overlay, onClick: handleClick }, event.title || "--")))), event.subtitle ? /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Box, { flex: 4 }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Flex, { direction: "row", align: "center" }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Text, { variant: "microcopy", truncate: true }, event.subtitle))) : null);
|
|
7139
7125
|
};
|
|
7140
|
-
var
|
|
7141
|
-
var
|
|
7142
|
-
var MonthChip = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels }) => {
|
|
7126
|
+
var MONTH_SLOT_HEIGHT = 24;
|
|
7127
|
+
var MonthChip = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels, monthEventStyle, monthEventMaxChars }) => {
|
|
7143
7128
|
const isStartDay = !day || !event.start || isSameDay(event.start, day);
|
|
7144
7129
|
const overlay = buildOverlay(event, overlayMode, renderEventDetail, labels, day ? `-m${day.getTime()}` : "");
|
|
7145
7130
|
const handleClick = onEventClick ? () => onEventClick(event.raw, event) : void 0;
|
|
@@ -7147,23 +7132,12 @@ var MonthChip = ({ event, day, overlayMode, renderEventDetail, onEventClick, lab
|
|
|
7147
7132
|
const startHasTime = event.start && (event.start.getHours() !== 0 || event.start.getMinutes() !== 0);
|
|
7148
7133
|
const time = isStartDay && startHasTime ? `${formatTime(event.start)} ` : "";
|
|
7149
7134
|
const prefix = isStartDay ? "" : "\u2192 ";
|
|
7150
|
-
const
|
|
7151
|
-
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7155
|
-
});
|
|
7156
|
-
return /* @__PURE__ */ import_react15.default.createElement(
|
|
7157
|
-
import_ui_extensions15.Image,
|
|
7158
|
-
{
|
|
7159
|
-
src: chip.src,
|
|
7160
|
-
width: chip.width,
|
|
7161
|
-
height: chip.height,
|
|
7162
|
-
alt: event.title || "",
|
|
7163
|
-
overlay,
|
|
7164
|
-
onClick: handleClick
|
|
7165
|
-
}
|
|
7166
|
-
);
|
|
7135
|
+
const maxChars = monthEventMaxChars != null ? monthEventMaxChars : monthLabelMaxChars(monthEventStyle);
|
|
7136
|
+
const label = truncateMonthLabel(`${prefix}${time}${event.title || "--"}`, maxChars);
|
|
7137
|
+
if (monthEventStyle === "tag") {
|
|
7138
|
+
return /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Tag, { variant: TAG_VARIANT[variant] || "default", overlay, onClick: handleClick }, label);
|
|
7139
|
+
}
|
|
7140
|
+
return /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Link, { overlay, onClick: handleClick }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.StatusTag, { variant: STATUS_VARIANT[variant] || "default" }, label));
|
|
7167
7141
|
};
|
|
7168
7142
|
var DayListItem = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels }) => {
|
|
7169
7143
|
const handleClick = onEventClick ? () => onEventClick(event.raw, event) : void 0;
|
|
@@ -7246,7 +7220,7 @@ var MonthView = ({
|
|
|
7246
7220
|
}) => {
|
|
7247
7221
|
const headers = weekdayLabels(weekStartsOn, hideWeekends, true);
|
|
7248
7222
|
const today = now || /* @__PURE__ */ new Date();
|
|
7249
|
-
const
|
|
7223
|
+
const slotSpacer = makeSpacerDataUri(MONTH_SLOT_HEIGHT, 1);
|
|
7250
7224
|
const renderCell = (day) => {
|
|
7251
7225
|
const dayEvents = eventsForDay(day);
|
|
7252
7226
|
const inMonth = isSameMonth(day, refDate);
|
|
@@ -7254,41 +7228,35 @@ var MonthView = ({
|
|
|
7254
7228
|
if (renderDayCell) return renderDayCell(day, dayEvents);
|
|
7255
7229
|
const shown = dayEvents.slice(0, maxEventsPerDay);
|
|
7256
7230
|
const hasOverflow = dayEvents.length > maxEventsPerDay;
|
|
7231
|
+
const heightSpacer = /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Image, { src: slotSpacer.src, width: slotSpacer.width, height: slotSpacer.height, alt: "" });
|
|
7232
|
+
const slotRow = (key, content) => /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Flex, { key, direction: "row", align: "center", gap: "flush" }, heightSpacer, content);
|
|
7257
7233
|
const slots = [];
|
|
7258
7234
|
for (let i = 0; i < maxEventsPerDay; i++) {
|
|
7259
7235
|
if (i < shown.length) {
|
|
7260
|
-
slots.push(/* @__PURE__ */ import_react15.default.createElement(MonthChip, {
|
|
7236
|
+
slots.push(slotRow(shown[i].key, /* @__PURE__ */ import_react15.default.createElement(MonthChip, { event: shown[i], day, ...chipProps })));
|
|
7261
7237
|
} else {
|
|
7262
|
-
slots.push(
|
|
7263
|
-
/* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Image, { key: `sp-${i}`, src: spacer24.src, width: spacer24.width, height: spacer24.height, alt: "" })
|
|
7264
|
-
);
|
|
7238
|
+
slots.push(/* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Image, { key: `sp-${i}`, src: slotSpacer.src, width: slotSpacer.width, height: slotSpacer.height, alt: "" }));
|
|
7265
7239
|
}
|
|
7266
7240
|
}
|
|
7267
7241
|
if (hasOverflow) {
|
|
7268
|
-
const more = makeMoreDataUri({
|
|
7269
|
-
label: labels.more(dayEvents.length - maxEventsPerDay),
|
|
7270
|
-
width: MONTH_COL_WIDTH,
|
|
7271
|
-
height: MONTH_CHIP_HEIGHT
|
|
7272
|
-
});
|
|
7273
7242
|
slots.push(
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
}
|
|
7243
|
+
slotRow(
|
|
7244
|
+
"more",
|
|
7245
|
+
/* @__PURE__ */ import_react15.default.createElement(
|
|
7246
|
+
import_ui_extensions15.Link,
|
|
7247
|
+
{
|
|
7248
|
+
overlay: /* @__PURE__ */ import_react15.default.createElement(import_experimental.Popover, { id: `cal-day-${day.getTime()}`, placement: "top", variant: "longform" }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Tile, { compact: true }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Flex, { direction: "column", gap: "sm" }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Flex, { direction: "row", justify: "center", align: "center", gap: "xs" }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Text, { format: { fontWeight: "bold" } }, String(dayEvents.length)), /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Text, { format: { fontWeight: "demibold" } }, labels.onThisDate)), /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Divider, null), dayEvents.map((event, i) => /* @__PURE__ */ import_react15.default.createElement(import_react15.default.Fragment, { key: event.key }, /* @__PURE__ */ import_react15.default.createElement(DayListItem, { event, day, ...chipProps }), i < dayEvents.length - 1 ? /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Divider, null) : null)))))
|
|
7249
|
+
},
|
|
7250
|
+
labels.more(dayEvents.length - maxEventsPerDay)
|
|
7251
|
+
)
|
|
7284
7252
|
)
|
|
7285
7253
|
);
|
|
7286
7254
|
} else {
|
|
7287
7255
|
slots.push(
|
|
7288
|
-
/* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Image, { key: "more-sp", src:
|
|
7256
|
+
/* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Image, { key: "more-sp", src: slotSpacer.src, width: slotSpacer.width, height: slotSpacer.height, alt: "" })
|
|
7289
7257
|
);
|
|
7290
7258
|
}
|
|
7291
|
-
return /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Flex, { direction: "row", align: "center", gap: "xs" }, isToday ? /* @__PURE__ */ import_react15.default.createElement(ColorDot, { variant: "info" }) : null, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Text, { variant: "microcopy", format: { fontWeight: inMonth ? "demibold" : "regular" } }, String(day.getDate()))), slots);
|
|
7259
|
+
return /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.AutoGrid, { columnWidth: MONTH_COL_WIDTH, gap: "flush" }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Flex, { direction: "row", align: "center", gap: "xs" }, isToday ? /* @__PURE__ */ import_react15.default.createElement(ColorDot, { variant: "info" }) : null, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Text, { variant: "microcopy", format: { fontWeight: inMonth ? "demibold" : "regular" } }, String(day.getDate()))), slots));
|
|
7292
7260
|
};
|
|
7293
7261
|
return /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Table, { bordered: true, flush: true }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.TableHead, null, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.TableRow, null, headers.map((h6) => /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.TableHeader, { key: h6, width: "min", align: "center" }, h6.toUpperCase())))), /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.TableBody, null, weeks.map((week, wi) => {
|
|
7294
7262
|
const days = hideWeekends ? week.filter((d) => d.getDay() !== 0 && d.getDay() !== 6) : week;
|
|
@@ -7331,6 +7299,7 @@ var TimeGridView = ({ days, now, hours, dayStartHour, dayEndHour, eventsForDay,
|
|
|
7331
7299
|
const today = now || /* @__PURE__ */ new Date();
|
|
7332
7300
|
const centerDays = days.length === 1;
|
|
7333
7301
|
const dayColWidth = days.length === 1 ? TIMEGRID_DAY_COL_SINGLE : TIMEGRID_DAY_COL;
|
|
7302
|
+
const weekTitleMaxChars = Math.max(6, Math.floor((TIMEGRID_DAY_COL - 46) / 6.6));
|
|
7334
7303
|
const todayInView = days.some((d) => isSameDay(d, today));
|
|
7335
7304
|
const nowHour = today.getHours();
|
|
7336
7305
|
const dayData = days.map((day) => {
|
|
@@ -7375,10 +7344,10 @@ var TimeGridView = ({ days, now, hours, dayStartHour, dayEndHour, eventsForDay,
|
|
|
7375
7344
|
} else if (mode === "cont") {
|
|
7376
7345
|
sub = `\u2191 cont. through ${endLabel}`;
|
|
7377
7346
|
}
|
|
7378
|
-
|
|
7347
|
+
const titleLabel = centerDays ? e.title || "--" : truncateMonthLabel(e.title || "--", weekTitleMaxChars);
|
|
7348
|
+
return /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Flex, { key: `${e.key}-${mode}-${hour}`, direction: "column", gap: "flush" }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Link, { overlay, onClick: handleClick }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.StatusTag, { variant: STATUS_VARIANT[variant] || "default" }, titleLabel)), sub ? /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Text, { variant: "microcopy" }, sub) : null);
|
|
7379
7349
|
};
|
|
7380
|
-
const
|
|
7381
|
-
const dayCell = (key, content) => /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.TableCell, { key, width: centerDays ? "max" : "min", align: "left" }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Flex, { direction: "column", gap: "xs" }, content, centerDays ? null : /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Image, { src: daySpacer.src, width: daySpacer.width, height: daySpacer.height, alt: "" })));
|
|
7350
|
+
const dayCell = (key, content) => /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.TableCell, { key, width: centerDays ? "max" : "min", align: "left" }, centerDays ? /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Flex, { direction: "column", gap: "xs" }, content) : /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.AutoGrid, { columnWidth: dayColWidth, gap: "flush" }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Flex, { direction: "column", gap: "xs" }, content)));
|
|
7382
7351
|
const slotSpacer = makeSpacerDataUri(HOUR_SLOT_HEIGHT, 1);
|
|
7383
7352
|
const emptyCell = null;
|
|
7384
7353
|
return /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.Table, { bordered: true, flush: true, density: "compact" }, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.TableHead, null, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.TableRow, null, /* @__PURE__ */ import_react15.default.createElement(import_ui_extensions15.TableHeader, { width: "min" }, "TIME"), dayData.map(({ day }) => {
|
|
@@ -7434,6 +7403,10 @@ var Calendar = (props) => {
|
|
|
7434
7403
|
weekStartsOn = 0,
|
|
7435
7404
|
hideWeekends = false,
|
|
7436
7405
|
maxEventsPerDay = DEFAULT_MAX_EVENTS_PER_DAY,
|
|
7406
|
+
// month-grid event token style: "statusTag" (dot + text, default) | "tag" (pill)
|
|
7407
|
+
monthEventStyle = "statusTag",
|
|
7408
|
+
// max characters for a month-cell label before "…" (default derived per style)
|
|
7409
|
+
monthEventMaxChars,
|
|
7437
7410
|
// time grid (week / day)
|
|
7438
7411
|
dayStartHour = DEFAULT_DAY_START_HOUR,
|
|
7439
7412
|
dayEndHour = DEFAULT_DAY_END_HOUR,
|
|
@@ -7653,7 +7626,15 @@ var Calendar = (props) => {
|
|
|
7653
7626
|
}
|
|
7654
7627
|
return formatMonthTitle(focusedDate);
|
|
7655
7628
|
}, [view, focusedDate, weekStartsOn, hideWeekends]);
|
|
7656
|
-
const
|
|
7629
|
+
const safeMonthEventStyle = MONTH_EVENT_STYLES.has(monthEventStyle) ? monthEventStyle : "statusTag";
|
|
7630
|
+
const chipProps = {
|
|
7631
|
+
overlayMode,
|
|
7632
|
+
renderEventDetail,
|
|
7633
|
+
onEventClick,
|
|
7634
|
+
labels,
|
|
7635
|
+
monthEventStyle: safeMonthEventStyle,
|
|
7636
|
+
monthEventMaxChars
|
|
7637
|
+
};
|
|
7657
7638
|
const timeZoneOptions = (0, import_react15.useMemo)(() => {
|
|
7658
7639
|
if (!showTimeZoneSelect) return null;
|
|
7659
7640
|
const base = (timeZoneOptionsProp && timeZoneOptionsProp.length ? timeZoneOptionsProp : DEFAULT_TIME_ZONES).map(
|
package/dist/index.mjs
CHANGED
|
@@ -6778,6 +6778,7 @@ var Feed = ({
|
|
|
6778
6778
|
import React14, { useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo5, useState as useState6 } from "react";
|
|
6779
6779
|
import {
|
|
6780
6780
|
Alert as Alert4,
|
|
6781
|
+
AutoGrid as AutoGrid3,
|
|
6781
6782
|
Box as Box6,
|
|
6782
6783
|
Button as Button8,
|
|
6783
6784
|
Divider as Divider4,
|
|
@@ -7009,21 +7010,6 @@ var formatTimeZoneLabel = (tz, atDate = /* @__PURE__ */ new Date()) => {
|
|
|
7009
7010
|
|
|
7010
7011
|
// src/calendar/svgChips.js
|
|
7011
7012
|
var toDataUri = (svg) => `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
|
7012
|
-
var escapeXml = (s) => String(s == null ? "" : s).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
7013
|
-
var truncateLabel = (value, max) => {
|
|
7014
|
-
const s = String(value == null ? "" : value);
|
|
7015
|
-
if (!max || s.length <= max) return s;
|
|
7016
|
-
return s.slice(0, Math.max(1, max - 1)).trimEnd() + "\u2026";
|
|
7017
|
-
};
|
|
7018
|
-
var CHIP_PALETTE = {
|
|
7019
|
-
default: { fill: "#7FD1DE", text: HS_TEXT_COLOR },
|
|
7020
|
-
info: { fill: "#00A4BD", text: "#FFFFFF" },
|
|
7021
|
-
success: { fill: "#00BDA5", text: "#FFFFFF" },
|
|
7022
|
-
warning: { fill: "#F5C26B", text: HS_TEXT_COLOR },
|
|
7023
|
-
error: { fill: "#F2545B", text: "#FFFFFF" },
|
|
7024
|
-
danger: { fill: "#F2545B", text: "#FFFFFF" }
|
|
7025
|
-
// StatusTag spells red "danger"; accept both
|
|
7026
|
-
};
|
|
7027
7013
|
var DOT_FILL = {
|
|
7028
7014
|
default: "#7C98B6",
|
|
7029
7015
|
info: "#00A4BD",
|
|
@@ -7038,23 +7024,6 @@ var makeDotDataUri = (variant = "default", size = 8) => {
|
|
|
7038
7024
|
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>`;
|
|
7039
7025
|
return { src: toDataUri(svg), width: size, height: size };
|
|
7040
7026
|
};
|
|
7041
|
-
var makeEventChipDataUri = (opts) => {
|
|
7042
|
-
const { label, width, height = 24, variant = "default" } = opts;
|
|
7043
|
-
const palette = CHIP_PALETTE[variant] || CHIP_PALETTE.default;
|
|
7044
|
-
const accentX = 5;
|
|
7045
|
-
const accentW = 3;
|
|
7046
|
-
const textX = accentX + accentW + 6;
|
|
7047
|
-
const rightPad = 8;
|
|
7048
|
-
const maxChars = Math.max(1, Math.floor((width - textX - rightPad) / 6));
|
|
7049
|
-
const text = truncateLabel(label, maxChars);
|
|
7050
|
-
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>`;
|
|
7051
|
-
return { src: toDataUri(svg), width, height };
|
|
7052
|
-
};
|
|
7053
|
-
var makeMoreDataUri = (opts) => {
|
|
7054
|
-
const { label, width, height = 24 } = opts;
|
|
7055
|
-
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>`;
|
|
7056
|
-
return { src: toDataUri(svg), width, height };
|
|
7057
|
-
};
|
|
7058
7027
|
var makeSpacerDataUri = (height = 24, width = 4) => {
|
|
7059
7028
|
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>`;
|
|
7060
7029
|
return { src: toDataUri(svg), width, height };
|
|
@@ -7150,6 +7119,24 @@ var STATUS_VARIANT = {
|
|
|
7150
7119
|
error: "danger",
|
|
7151
7120
|
danger: "danger"
|
|
7152
7121
|
};
|
|
7122
|
+
var TAG_VARIANT = {
|
|
7123
|
+
default: "default",
|
|
7124
|
+
info: "info",
|
|
7125
|
+
success: "success",
|
|
7126
|
+
warning: "warning",
|
|
7127
|
+
error: "error",
|
|
7128
|
+
danger: "error"
|
|
7129
|
+
};
|
|
7130
|
+
var MONTH_EVENT_STYLES = /* @__PURE__ */ new Set(["statusTag", "tag"]);
|
|
7131
|
+
var monthLabelMaxChars = (style) => {
|
|
7132
|
+
const overhead = style === "tag" ? 34 : 46;
|
|
7133
|
+
return Math.max(6, Math.floor((MONTH_COL_WIDTH - overhead) / 6.6));
|
|
7134
|
+
};
|
|
7135
|
+
var truncateMonthLabel = (value, max) => {
|
|
7136
|
+
const s = String(value == null ? "" : value);
|
|
7137
|
+
if (!max || s.length <= max) return s;
|
|
7138
|
+
return s.slice(0, max).trimEnd();
|
|
7139
|
+
};
|
|
7153
7140
|
var MONTH_COL_WIDTH = 160;
|
|
7154
7141
|
var TIMEGRID_DAY_COL = 150;
|
|
7155
7142
|
var TIMEGRID_DAY_COL_SINGLE = 560;
|
|
@@ -7168,7 +7155,7 @@ var EventDetail = ({ event, labels }) => {
|
|
|
7168
7155
|
when = `${formatDayTitle(start)} \u2013 ${formatDayTitle(end)}`;
|
|
7169
7156
|
}
|
|
7170
7157
|
}
|
|
7171
|
-
return /* @__PURE__ */ React14.createElement(Flex9, { direction: "column", gap: "xs" }, /* @__PURE__ */ React14.createElement(Text7, { format: { fontWeight: "demibold" } }, title || "--"), when ? /* @__PURE__ */ React14.createElement(Text7, { variant: "microcopy" }, when) : null, subtitle ? /* @__PURE__ */ React14.createElement(Text7,
|
|
7158
|
+
return /* @__PURE__ */ React14.createElement(Flex9, { direction: "column", gap: "xs" }, /* @__PURE__ */ React14.createElement(Text7, { format: { fontWeight: "demibold" }, truncate: true }, title || "--"), when ? /* @__PURE__ */ React14.createElement(Text7, { variant: "microcopy", truncate: true }, when) : null, subtitle ? /* @__PURE__ */ React14.createElement(Text7, { truncate: true }, subtitle) : null, href ? /* @__PURE__ */ React14.createElement(Link6, { href: href.url, external: href.external }, labels.open) : null);
|
|
7172
7159
|
};
|
|
7173
7160
|
var buildOverlay = (event, mode, renderEventDetail, labels, idSuffix = "") => {
|
|
7174
7161
|
if (mode === "none") return void 0;
|
|
@@ -7180,7 +7167,7 @@ var buildOverlay = (event, mode, renderEventDetail, labels, idSuffix = "") => {
|
|
|
7180
7167
|
if (mode === "panel") {
|
|
7181
7168
|
return /* @__PURE__ */ React14.createElement(Panel, { id, title: event.title || labels.open, width: "small", variant: "modal" }, /* @__PURE__ */ React14.createElement(PanelBody, null, body));
|
|
7182
7169
|
}
|
|
7183
|
-
return /* @__PURE__ */ React14.createElement(Popover, { id, placement: "bottom" }, /* @__PURE__ */ React14.createElement(Tile5, { compact: true }, body));
|
|
7170
|
+
return /* @__PURE__ */ React14.createElement(Popover, { id, placement: "bottom", variant: "longform" }, /* @__PURE__ */ React14.createElement(Tile5, { compact: true }, body));
|
|
7184
7171
|
};
|
|
7185
7172
|
var AgendaEventRow = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels }) => {
|
|
7186
7173
|
const variant = VALID_VARIANTS.has(event.color) ? event.color : "default";
|
|
@@ -7189,9 +7176,8 @@ var AgendaEventRow = ({ event, day, overlayMode, renderEventDetail, onEventClick
|
|
|
7189
7176
|
const timeLabel = isAllDayEvent(event) ? labels.allDay : formatTime(event.start);
|
|
7190
7177
|
return /* @__PURE__ */ React14.createElement(Flex9, { direction: "row", align: "center", gap: "sm" }, /* @__PURE__ */ React14.createElement(Box6, { flex: 2 }, /* @__PURE__ */ React14.createElement(Flex9, { direction: "row", align: "center" }, /* @__PURE__ */ React14.createElement(Text7, { variant: "microcopy", format: { fontWeight: "demibold" } }, timeLabel))), /* @__PURE__ */ React14.createElement(Box6, { flex: 11 }, /* @__PURE__ */ React14.createElement(Flex9, { direction: "row", align: "center", gap: "xs" }, /* @__PURE__ */ React14.createElement(ColorDot, { variant }), /* @__PURE__ */ React14.createElement(Text7, { truncate: true }, /* @__PURE__ */ React14.createElement(Link6, { overlay, onClick: handleClick }, event.title || "--")))), event.subtitle ? /* @__PURE__ */ React14.createElement(Box6, { flex: 4 }, /* @__PURE__ */ React14.createElement(Flex9, { direction: "row", align: "center" }, /* @__PURE__ */ React14.createElement(Text7, { variant: "microcopy", truncate: true }, event.subtitle))) : null);
|
|
7191
7178
|
};
|
|
7192
|
-
var
|
|
7193
|
-
var
|
|
7194
|
-
var MonthChip = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels }) => {
|
|
7179
|
+
var MONTH_SLOT_HEIGHT = 24;
|
|
7180
|
+
var MonthChip = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels, monthEventStyle, monthEventMaxChars }) => {
|
|
7195
7181
|
const isStartDay = !day || !event.start || isSameDay(event.start, day);
|
|
7196
7182
|
const overlay = buildOverlay(event, overlayMode, renderEventDetail, labels, day ? `-m${day.getTime()}` : "");
|
|
7197
7183
|
const handleClick = onEventClick ? () => onEventClick(event.raw, event) : void 0;
|
|
@@ -7199,23 +7185,12 @@ var MonthChip = ({ event, day, overlayMode, renderEventDetail, onEventClick, lab
|
|
|
7199
7185
|
const startHasTime = event.start && (event.start.getHours() !== 0 || event.start.getMinutes() !== 0);
|
|
7200
7186
|
const time = isStartDay && startHasTime ? `${formatTime(event.start)} ` : "";
|
|
7201
7187
|
const prefix = isStartDay ? "" : "\u2192 ";
|
|
7202
|
-
const
|
|
7203
|
-
|
|
7204
|
-
|
|
7205
|
-
|
|
7206
|
-
|
|
7207
|
-
});
|
|
7208
|
-
return /* @__PURE__ */ React14.createElement(
|
|
7209
|
-
Image5,
|
|
7210
|
-
{
|
|
7211
|
-
src: chip.src,
|
|
7212
|
-
width: chip.width,
|
|
7213
|
-
height: chip.height,
|
|
7214
|
-
alt: event.title || "",
|
|
7215
|
-
overlay,
|
|
7216
|
-
onClick: handleClick
|
|
7217
|
-
}
|
|
7218
|
-
);
|
|
7188
|
+
const maxChars = monthEventMaxChars != null ? monthEventMaxChars : monthLabelMaxChars(monthEventStyle);
|
|
7189
|
+
const label = truncateMonthLabel(`${prefix}${time}${event.title || "--"}`, maxChars);
|
|
7190
|
+
if (monthEventStyle === "tag") {
|
|
7191
|
+
return /* @__PURE__ */ React14.createElement(Tag5, { variant: TAG_VARIANT[variant] || "default", overlay, onClick: handleClick }, label);
|
|
7192
|
+
}
|
|
7193
|
+
return /* @__PURE__ */ React14.createElement(Link6, { overlay, onClick: handleClick }, /* @__PURE__ */ React14.createElement(StatusTag2, { variant: STATUS_VARIANT[variant] || "default" }, label));
|
|
7219
7194
|
};
|
|
7220
7195
|
var DayListItem = ({ event, day, overlayMode, renderEventDetail, onEventClick, labels }) => {
|
|
7221
7196
|
const handleClick = onEventClick ? () => onEventClick(event.raw, event) : void 0;
|
|
@@ -7298,7 +7273,7 @@ var MonthView = ({
|
|
|
7298
7273
|
}) => {
|
|
7299
7274
|
const headers = weekdayLabels(weekStartsOn, hideWeekends, true);
|
|
7300
7275
|
const today = now || /* @__PURE__ */ new Date();
|
|
7301
|
-
const
|
|
7276
|
+
const slotSpacer = makeSpacerDataUri(MONTH_SLOT_HEIGHT, 1);
|
|
7302
7277
|
const renderCell = (day) => {
|
|
7303
7278
|
const dayEvents = eventsForDay(day);
|
|
7304
7279
|
const inMonth = isSameMonth(day, refDate);
|
|
@@ -7306,41 +7281,35 @@ var MonthView = ({
|
|
|
7306
7281
|
if (renderDayCell) return renderDayCell(day, dayEvents);
|
|
7307
7282
|
const shown = dayEvents.slice(0, maxEventsPerDay);
|
|
7308
7283
|
const hasOverflow = dayEvents.length > maxEventsPerDay;
|
|
7284
|
+
const heightSpacer = /* @__PURE__ */ React14.createElement(Image5, { src: slotSpacer.src, width: slotSpacer.width, height: slotSpacer.height, alt: "" });
|
|
7285
|
+
const slotRow = (key, content) => /* @__PURE__ */ React14.createElement(Flex9, { key, direction: "row", align: "center", gap: "flush" }, heightSpacer, content);
|
|
7309
7286
|
const slots = [];
|
|
7310
7287
|
for (let i = 0; i < maxEventsPerDay; i++) {
|
|
7311
7288
|
if (i < shown.length) {
|
|
7312
|
-
slots.push(/* @__PURE__ */ React14.createElement(MonthChip, {
|
|
7289
|
+
slots.push(slotRow(shown[i].key, /* @__PURE__ */ React14.createElement(MonthChip, { event: shown[i], day, ...chipProps })));
|
|
7313
7290
|
} else {
|
|
7314
|
-
slots.push(
|
|
7315
|
-
/* @__PURE__ */ React14.createElement(Image5, { key: `sp-${i}`, src: spacer24.src, width: spacer24.width, height: spacer24.height, alt: "" })
|
|
7316
|
-
);
|
|
7291
|
+
slots.push(/* @__PURE__ */ React14.createElement(Image5, { key: `sp-${i}`, src: slotSpacer.src, width: slotSpacer.width, height: slotSpacer.height, alt: "" }));
|
|
7317
7292
|
}
|
|
7318
7293
|
}
|
|
7319
7294
|
if (hasOverflow) {
|
|
7320
|
-
const more = makeMoreDataUri({
|
|
7321
|
-
label: labels.more(dayEvents.length - maxEventsPerDay),
|
|
7322
|
-
width: MONTH_COL_WIDTH,
|
|
7323
|
-
height: MONTH_CHIP_HEIGHT
|
|
7324
|
-
});
|
|
7325
7295
|
slots.push(
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
|
|
7330
|
-
|
|
7331
|
-
|
|
7332
|
-
|
|
7333
|
-
|
|
7334
|
-
|
|
7335
|
-
}
|
|
7296
|
+
slotRow(
|
|
7297
|
+
"more",
|
|
7298
|
+
/* @__PURE__ */ React14.createElement(
|
|
7299
|
+
Link6,
|
|
7300
|
+
{
|
|
7301
|
+
overlay: /* @__PURE__ */ React14.createElement(Popover, { id: `cal-day-${day.getTime()}`, placement: "top", variant: "longform" }, /* @__PURE__ */ React14.createElement(Tile5, { compact: true }, /* @__PURE__ */ React14.createElement(Flex9, { direction: "column", gap: "sm" }, /* @__PURE__ */ React14.createElement(Flex9, { direction: "row", justify: "center", align: "center", gap: "xs" }, /* @__PURE__ */ React14.createElement(Text7, { format: { fontWeight: "bold" } }, String(dayEvents.length)), /* @__PURE__ */ React14.createElement(Text7, { format: { fontWeight: "demibold" } }, labels.onThisDate)), /* @__PURE__ */ React14.createElement(Divider4, null), dayEvents.map((event, i) => /* @__PURE__ */ React14.createElement(React14.Fragment, { key: event.key }, /* @__PURE__ */ React14.createElement(DayListItem, { event, day, ...chipProps }), i < dayEvents.length - 1 ? /* @__PURE__ */ React14.createElement(Divider4, null) : null)))))
|
|
7302
|
+
},
|
|
7303
|
+
labels.more(dayEvents.length - maxEventsPerDay)
|
|
7304
|
+
)
|
|
7336
7305
|
)
|
|
7337
7306
|
);
|
|
7338
7307
|
} else {
|
|
7339
7308
|
slots.push(
|
|
7340
|
-
/* @__PURE__ */ React14.createElement(Image5, { key: "more-sp", src:
|
|
7309
|
+
/* @__PURE__ */ React14.createElement(Image5, { key: "more-sp", src: slotSpacer.src, width: slotSpacer.width, height: slotSpacer.height, alt: "" })
|
|
7341
7310
|
);
|
|
7342
7311
|
}
|
|
7343
|
-
return /* @__PURE__ */ React14.createElement(Flex9, { direction: "column", gap: "xs" }, /* @__PURE__ */ React14.createElement(Flex9, { direction: "row", align: "center", gap: "xs" }, isToday ? /* @__PURE__ */ React14.createElement(ColorDot, { variant: "info" }) : null, /* @__PURE__ */ React14.createElement(Text7, { variant: "microcopy", format: { fontWeight: inMonth ? "demibold" : "regular" } }, String(day.getDate()))), slots);
|
|
7312
|
+
return /* @__PURE__ */ React14.createElement(AutoGrid3, { columnWidth: MONTH_COL_WIDTH, gap: "flush" }, /* @__PURE__ */ React14.createElement(Flex9, { direction: "column", gap: "xs" }, /* @__PURE__ */ React14.createElement(Flex9, { direction: "row", align: "center", gap: "xs" }, isToday ? /* @__PURE__ */ React14.createElement(ColorDot, { variant: "info" }) : null, /* @__PURE__ */ React14.createElement(Text7, { variant: "microcopy", format: { fontWeight: inMonth ? "demibold" : "regular" } }, String(day.getDate()))), slots));
|
|
7344
7313
|
};
|
|
7345
7314
|
return /* @__PURE__ */ React14.createElement(Table2, { bordered: true, flush: true }, /* @__PURE__ */ React14.createElement(TableHead2, null, /* @__PURE__ */ React14.createElement(TableRow2, null, headers.map((h6) => /* @__PURE__ */ React14.createElement(TableHeader2, { key: h6, width: "min", align: "center" }, h6.toUpperCase())))), /* @__PURE__ */ React14.createElement(TableBody2, null, weeks.map((week, wi) => {
|
|
7346
7315
|
const days = hideWeekends ? week.filter((d) => d.getDay() !== 0 && d.getDay() !== 6) : week;
|
|
@@ -7383,6 +7352,7 @@ var TimeGridView = ({ days, now, hours, dayStartHour, dayEndHour, eventsForDay,
|
|
|
7383
7352
|
const today = now || /* @__PURE__ */ new Date();
|
|
7384
7353
|
const centerDays = days.length === 1;
|
|
7385
7354
|
const dayColWidth = days.length === 1 ? TIMEGRID_DAY_COL_SINGLE : TIMEGRID_DAY_COL;
|
|
7355
|
+
const weekTitleMaxChars = Math.max(6, Math.floor((TIMEGRID_DAY_COL - 46) / 6.6));
|
|
7386
7356
|
const todayInView = days.some((d) => isSameDay(d, today));
|
|
7387
7357
|
const nowHour = today.getHours();
|
|
7388
7358
|
const dayData = days.map((day) => {
|
|
@@ -7427,10 +7397,10 @@ var TimeGridView = ({ days, now, hours, dayStartHour, dayEndHour, eventsForDay,
|
|
|
7427
7397
|
} else if (mode === "cont") {
|
|
7428
7398
|
sub = `\u2191 cont. through ${endLabel}`;
|
|
7429
7399
|
}
|
|
7430
|
-
|
|
7400
|
+
const titleLabel = centerDays ? e.title || "--" : truncateMonthLabel(e.title || "--", weekTitleMaxChars);
|
|
7401
|
+
return /* @__PURE__ */ React14.createElement(Flex9, { key: `${e.key}-${mode}-${hour}`, direction: "column", gap: "flush" }, /* @__PURE__ */ React14.createElement(Link6, { overlay, onClick: handleClick }, /* @__PURE__ */ React14.createElement(StatusTag2, { variant: STATUS_VARIANT[variant] || "default" }, titleLabel)), sub ? /* @__PURE__ */ React14.createElement(Text7, { variant: "microcopy" }, sub) : null);
|
|
7431
7402
|
};
|
|
7432
|
-
const
|
|
7433
|
-
const dayCell = (key, content) => /* @__PURE__ */ React14.createElement(TableCell2, { key, width: centerDays ? "max" : "min", align: "left" }, /* @__PURE__ */ React14.createElement(Flex9, { direction: "column", gap: "xs" }, content, centerDays ? null : /* @__PURE__ */ React14.createElement(Image5, { src: daySpacer.src, width: daySpacer.width, height: daySpacer.height, alt: "" })));
|
|
7403
|
+
const dayCell = (key, content) => /* @__PURE__ */ React14.createElement(TableCell2, { key, width: centerDays ? "max" : "min", align: "left" }, centerDays ? /* @__PURE__ */ React14.createElement(Flex9, { direction: "column", gap: "xs" }, content) : /* @__PURE__ */ React14.createElement(AutoGrid3, { columnWidth: dayColWidth, gap: "flush" }, /* @__PURE__ */ React14.createElement(Flex9, { direction: "column", gap: "xs" }, content)));
|
|
7434
7404
|
const slotSpacer = makeSpacerDataUri(HOUR_SLOT_HEIGHT, 1);
|
|
7435
7405
|
const emptyCell = null;
|
|
7436
7406
|
return /* @__PURE__ */ React14.createElement(Table2, { bordered: true, flush: true, density: "compact" }, /* @__PURE__ */ React14.createElement(TableHead2, null, /* @__PURE__ */ React14.createElement(TableRow2, null, /* @__PURE__ */ React14.createElement(TableHeader2, { width: "min" }, "TIME"), dayData.map(({ day }) => {
|
|
@@ -7486,6 +7456,10 @@ var Calendar = (props) => {
|
|
|
7486
7456
|
weekStartsOn = 0,
|
|
7487
7457
|
hideWeekends = false,
|
|
7488
7458
|
maxEventsPerDay = DEFAULT_MAX_EVENTS_PER_DAY,
|
|
7459
|
+
// month-grid event token style: "statusTag" (dot + text, default) | "tag" (pill)
|
|
7460
|
+
monthEventStyle = "statusTag",
|
|
7461
|
+
// max characters for a month-cell label before "…" (default derived per style)
|
|
7462
|
+
monthEventMaxChars,
|
|
7489
7463
|
// time grid (week / day)
|
|
7490
7464
|
dayStartHour = DEFAULT_DAY_START_HOUR,
|
|
7491
7465
|
dayEndHour = DEFAULT_DAY_END_HOUR,
|
|
@@ -7705,7 +7679,15 @@ var Calendar = (props) => {
|
|
|
7705
7679
|
}
|
|
7706
7680
|
return formatMonthTitle(focusedDate);
|
|
7707
7681
|
}, [view, focusedDate, weekStartsOn, hideWeekends]);
|
|
7708
|
-
const
|
|
7682
|
+
const safeMonthEventStyle = MONTH_EVENT_STYLES.has(monthEventStyle) ? monthEventStyle : "statusTag";
|
|
7683
|
+
const chipProps = {
|
|
7684
|
+
overlayMode,
|
|
7685
|
+
renderEventDetail,
|
|
7686
|
+
onEventClick,
|
|
7687
|
+
labels,
|
|
7688
|
+
monthEventStyle: safeMonthEventStyle,
|
|
7689
|
+
monthEventMaxChars
|
|
7690
|
+
};
|
|
7709
7691
|
const timeZoneOptions = useMemo5(() => {
|
|
7710
7692
|
if (!showTimeZoneSelect) return null;
|
|
7711
7693
|
const base = (timeZoneOptionsProp && timeZoneOptionsProp.length ? timeZoneOptionsProp : DEFAULT_TIME_ZONES).map(
|
package/package.json
CHANGED
package/src/calendar/README.md
CHANGED
|
@@ -230,6 +230,8 @@ How it works: each event instant is converted to a "wall-clock" `Date` in the ac
|
|
|
230
230
|
| `weekStartsOn` | `0 \| 1` | `0` | 0 = Sunday, 1 = Monday. |
|
|
231
231
|
| `hideWeekends` | `boolean` | `false` | Hide Sat/Sun in month + week views. |
|
|
232
232
|
| `maxEventsPerDay` | `number` | `3` | Chips per month cell before "+N more". |
|
|
233
|
+
| `monthEventStyle` | `"statusTag" \| "tag"` | `"statusTag"` | Month-cell event token: `statusTag` (colored dot + text, matches week/day) or `tag` (bordered pill). Both truncate and hold a fixed height as columns narrow. |
|
|
234
|
+
| `monthEventMaxChars` | `number` | per-style, from column width | Max characters for a month-cell label before "…". Labels are truncated up front so every token truncates consistently (the tag's native truncation measures unreliably while the table is still sizing columns). |
|
|
233
235
|
| `dayStartHour` | `number` | `8` | First hour row in week/day (0–23). |
|
|
234
236
|
| `dayEndHour` | `number` | `20` | Last hour row in week/day (0–23). |
|
|
235
237
|
| `timeZone` | `string` | — | Controlled IANA zone (e.g. `"America/Chicago"`). Setting it opts into the tz layer; all times/placement/grouping resolve here. |
|
package/src/calendar/index.d.ts
CHANGED
|
@@ -125,6 +125,19 @@ export interface CalendarProps<Event = Record<string, unknown>> {
|
|
|
125
125
|
hideWeekends?: boolean;
|
|
126
126
|
/** Max chips per day cell in month view before collapsing to "N more". */
|
|
127
127
|
maxEventsPerDay?: number;
|
|
128
|
+
/**
|
|
129
|
+
* Month-cell event token style. `"statusTag"` (default) renders a colored dot +
|
|
130
|
+
* text matching the week/day grid; `"tag"` renders a bordered pill. Both
|
|
131
|
+
* truncate and hold a fixed height as columns narrow.
|
|
132
|
+
*/
|
|
133
|
+
monthEventStyle?: "statusTag" | "tag";
|
|
134
|
+
/**
|
|
135
|
+
* Max characters for a month-cell event label before it's truncated with "…".
|
|
136
|
+
* Defaults to a per-style budget derived from the column width. Labels are
|
|
137
|
+
* truncated up front (not just via the tag's native TruncateString) so every
|
|
138
|
+
* token truncates consistently regardless of the table's column-sizing timing.
|
|
139
|
+
*/
|
|
140
|
+
monthEventMaxChars?: number;
|
|
128
141
|
|
|
129
142
|
// Time grid (week / day views)
|
|
130
143
|
/** First hour row in week/day view (0–23). Default 8. */
|