gridsmith-ui 0.25.0 → 0.26.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/dist/charts.js.map +1 -1
- package/dist/chat.js +3 -3
- package/dist/{chunk-W7GCEJEH.js → chunk-CYN5O567.js} +5 -5
- package/dist/{chunk-W7GCEJEH.js.map → chunk-CYN5O567.js.map} +1 -1
- package/dist/{chunk-FHMCAOAH.js → chunk-EX64MN2U.js} +3 -3
- package/dist/{chunk-FHMCAOAH.js.map → chunk-EX64MN2U.js.map} +1 -1
- package/dist/{chunk-HYMXAIXN.js → chunk-HXVXJUGV.js} +7 -7
- package/dist/chunk-HXVXJUGV.js.map +1 -0
- package/dist/{chunk-3CUKJ4VP.js → chunk-KWLNEH53.js} +5 -5
- package/dist/{chunk-3CUKJ4VP.js.map → chunk-KWLNEH53.js.map} +1 -1
- package/dist/{chunk-QGSCF7PN.js → chunk-MYIJNVTK.js} +4 -4
- package/dist/{chunk-QGSCF7PN.js.map → chunk-MYIJNVTK.js.map} +1 -1
- package/dist/{chunk-2YSEME33.js → chunk-SFY2KMHG.js} +63 -6
- package/dist/chunk-SFY2KMHG.js.map +1 -0
- package/dist/{chunk-JXANCXK6.js → chunk-ZI3OQDET.js} +18 -4
- package/dist/chunk-ZI3OQDET.js.map +1 -0
- package/dist/{chunk-HZIP4EJI.js → chunk-ZYVXV4WC.js} +3 -3
- package/dist/{chunk-HZIP4EJI.js.map → chunk-ZYVXV4WC.js.map} +1 -1
- package/dist/data-grid.js +4 -4
- package/dist/editor-mentions.js +1 -1
- package/dist/editor.js +2 -2
- package/dist/{feather-W26ERBQV.js → feather-VFWLAILO.js} +4 -3
- package/dist/feather-VFWLAILO.js.map +1 -0
- package/dist/{heroicons-MY43466C.js → heroicons-H3Z7DFCF.js} +4 -3
- package/dist/heroicons-H3Z7DFCF.js.map +1 -0
- package/dist/icons.d.ts +1 -1
- package/dist/icons.js +1 -1
- package/dist/index.d.ts +53 -4
- package/dist/index.js +1192 -981
- package/dist/index.js.map +1 -1
- package/dist/kanban.js +4 -5
- package/dist/kanban.js.map +1 -1
- package/dist/{lucide-CMPVM3PS.js → lucide-MR32KM4G.js} +4 -3
- package/dist/lucide-MR32KM4G.js.map +1 -0
- package/dist/{phosphor-RMHZOW2O.js → phosphor-ABQQL5N5.js} +4 -3
- package/dist/phosphor-ABQQL5N5.js.map +1 -0
- package/dist/resizable.js +5 -6
- package/dist/resizable.js.map +1 -1
- package/dist/roots.css +18 -0
- package/dist/{tabler-MJVEYHA5.js → tabler-ANUSY4D2.js} +4 -3
- package/dist/tabler-ANUSY4D2.js.map +1 -0
- package/dist/tokens.css +6 -0
- package/dist/virtualized.js +4 -4
- package/dist-static/tokens.css +6 -0
- package/package.json +1 -1
- package/dist/chunk-2YSEME33.js.map +0 -1
- package/dist/chunk-HYMXAIXN.js.map +0 -1
- package/dist/chunk-JXANCXK6.js.map +0 -1
- package/dist/chunk-WOVYHFUD.js +0 -50
- package/dist/chunk-WOVYHFUD.js.map +0 -1
- package/dist/feather-W26ERBQV.js.map +0 -1
- package/dist/heroicons-MY43466C.js.map +0 -1
- package/dist/lucide-CMPVM3PS.js.map +0 -1
- package/dist/phosphor-RMHZOW2O.js.map +0 -1
- package/dist/tabler-MJVEYHA5.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { inferColumnKinds, useCardsSwitch, CARDS_BELOW, kindOfRenderedText, CardValue } from './chunk-OTCEJN64.js';
|
|
2
|
-
import { useWholeListCheck, pagerPart, Pagination, Input, CHECK_FILL, Dropdown, FilterRowContext, SWITCH_KNOB_ON, SWITCH_KNOB_OFF, SWITCH_KNOB_MOTION, SWITCH_TRACK_ON, SWITCH_TRACK_OFF, useFieldControl, useField, Label, InlineFieldError, AddAnotherRowCtx, Field } from './chunk-
|
|
3
|
-
export { Dropdown, Field, InlineFieldError, Input, Label, NumberInput, Pagination, Popover, Textarea, Toggle, usePagination } from './chunk-
|
|
4
|
-
import { useAppShell, REACT_VERSION_PROBLEM, Breadcrumbs, useCrumbFollow, crumbGoes, useOverlayMark, useDirtyGuard, useScrollbarInset, DrawerFooterCtx, OverlayMarkScope, OverlayCloseCtx, insetLessScrollbar, DiscardConfirm, OVERLAY_ROOT_ATTR, OverlayMarkCtx, useCompact, useElementWidth, DrawerPanel, useCloseSettle, Drawer, useRememberedWidth, pxOf, ResizeEdge, defaultMaxWidth } from './chunk-
|
|
5
|
-
export { AppShell, Breadcrumbs, Drawer, SkipLink, useAppShell, useUnsavedChanges } from './chunk-
|
|
6
|
-
import { Button, ControlSizeContext, triggerType, Spinner, useShellPreferences, PREFERENCE_HOUSE_DEFAULTS, preferenceActionKey } from './chunk-
|
|
7
|
-
export { Button, ButtonSizeContext, ControlSizeContext, PreferencesContext, Spinner, preferenceActionKey, usePreferences } from './chunk-
|
|
2
|
+
import { useWholeListCheck, pagerPart, Pagination, Input, CHECK_FILL, Dropdown, FilterRowContext, SWITCH_KNOB_ON, SWITCH_KNOB_OFF, SWITCH_KNOB_MOTION, SWITCH_TRACK_ON, SWITCH_TRACK_OFF, useFieldControl, useField, Label, InlineFieldError, AddAnotherRowCtx, Field } from './chunk-CYN5O567.js';
|
|
3
|
+
export { Dropdown, Field, InlineFieldError, Input, Label, NumberInput, Pagination, Popover, Textarea, Toggle, usePagination } from './chunk-CYN5O567.js';
|
|
4
|
+
import { useAppShell, REACT_VERSION_PROBLEM, Breadcrumbs, useCrumbFollow, crumbGoes, useOverlayMark, useDirtyGuard, useScrollbarInset, DrawerFooterCtx, OverlayMarkScope, OverlayCloseCtx, insetLessScrollbar, DiscardConfirm, OVERLAY_ROOT_ATTR, OverlayMarkCtx, useCompact, useElementWidth, DrawerPanel, useCloseSettle, Drawer, useRememberedWidth, pxOf, ResizeEdge, defaultMaxWidth } from './chunk-KWLNEH53.js';
|
|
5
|
+
export { AppShell, Breadcrumbs, Drawer, SkipLink, useAppShell, useUnsavedChanges } from './chunk-KWLNEH53.js';
|
|
6
|
+
import { Button, ControlSizeContext, triggerType, Spinner, useShellPreferences, PREFERENCE_HOUSE_DEFAULTS, preferenceActionKey } from './chunk-ZYVXV4WC.js';
|
|
7
|
+
export { Button, ButtonSizeContext, ControlSizeContext, PreferencesContext, Spinner, preferenceActionKey, usePreferences } from './chunk-ZYVXV4WC.js';
|
|
8
8
|
import { Skeleton, TITLE_TEXT, formatLocale } from './chunk-X2HEV7FB.js';
|
|
9
9
|
export { Skeleton } from './chunk-X2HEV7FB.js';
|
|
10
10
|
import { useScrollEdges, EDGE_FADE } from './chunk-3BRQRKDO.js';
|
|
@@ -14,18 +14,18 @@ import { FormChangeCtx, useReportedChange, useOptionalFormContext, FormCtx } fro
|
|
|
14
14
|
export { useFormContext } from './chunk-XVB55M3N.js';
|
|
15
15
|
import { Avatar, foldForSearch, useActiveOptionInView, shownMentions, matchMentions, mentionOptionId, MentionList, initialsOf } from './chunk-RWKCAKN3.js';
|
|
16
16
|
export { Avatar } from './chunk-RWKCAKN3.js';
|
|
17
|
-
import { Link } from './chunk-
|
|
18
|
-
export { CodeBlock, Divider, Link } from './chunk-
|
|
19
|
-
import { useFillHeight, FillContext } from './chunk-
|
|
17
|
+
import { Link } from './chunk-MYIJNVTK.js';
|
|
18
|
+
export { CodeBlock, Divider, Link } from './chunk-MYIJNVTK.js';
|
|
19
|
+
import { useFillHeight, FillContext, useKeyboardScroll, FOCUS_INSET } from './chunk-SFY2KMHG.js';
|
|
20
20
|
import { CardSurfaceCtx, useScrollsInside, SplitPaneCtx, RowsCtx, PageActionsCtx, SurfaceBoundary, useFramesItself, TableCardCtx } from './chunk-QM4SJKWV.js';
|
|
21
|
-
import { FOCUSABLE, usePopupFocus, FIELD, ZOOM_KEYS, useOverlayLayer, useFocusTrap, useFocusBeforeOpen, rememberFocus, focusInitial, OVERLAY_CLOSE_ATTR, rovingTabStop, useGridKeyboard, focusAfterRemoval, useNonModalDialog, useReturnFocus
|
|
22
|
-
export { useGridKeyboard } from './chunk-
|
|
23
|
-
import { Badge } from './chunk-
|
|
24
|
-
export { Badge } from './chunk-
|
|
21
|
+
import { FOCUSABLE, usePopupFocus, FIELD, ZOOM_KEYS, useOverlayLayer, useFocusTrap, useFocusBeforeOpen, rememberFocus, focusInitial, OVERLAY_CLOSE_ATTR, rovingTabStop, useGridKeyboard, focusAfterRemoval, useNonModalDialog, useReturnFocus } from './chunk-ZI3OQDET.js';
|
|
22
|
+
export { useGridKeyboard } from './chunk-ZI3OQDET.js';
|
|
23
|
+
import { Badge } from './chunk-EX64MN2U.js';
|
|
24
|
+
export { Badge } from './chunk-EX64MN2U.js';
|
|
25
25
|
import { useTextOverflow, Tooltip } from './chunk-MD2EFMES.js';
|
|
26
26
|
export { Tooltip, useTextOverflow } from './chunk-MD2EFMES.js';
|
|
27
27
|
import { mergeRefs, Slot } from './chunk-7Q46JXSK.js';
|
|
28
|
-
import { Icon, slotIcon, warnOnce } from './chunk-
|
|
28
|
+
import { Icon, slotIcon, warnOnce } from './chunk-HXVXJUGV.js';
|
|
29
29
|
import { usePosition } from './chunk-HP7WUZPK.js';
|
|
30
30
|
import { useLatest } from './chunk-WH2FUFAC.js';
|
|
31
31
|
import { cn, GLASS_SURFACE, GLASS_BACKDROP, GLASS_DROPDOWN, lockBodyScroll, unlockBodyScroll, OVERLAY_SURFACE, GLASS_OVERLAY, ERROR_HAS_FOCUS_RING, HAS_FOCUS_RING, ACTIVE_RING, ERROR_ACTIVE_RING, ERROR_FOCUS_RING, FOCUS_RING, FOCUS_WITHIN_RING } from './chunk-M2QRNBDQ.js';
|
|
@@ -247,7 +247,7 @@ function Combobox({ value, onChange: onChangeProp, options, placeholder = "Searc
|
|
|
247
247
|
const listboxId = useId();
|
|
248
248
|
const pos = usePosition(triggerRef, listRef, open, { side: "bottom", align: "start", offset: 4, flip: true });
|
|
249
249
|
const filtered = options.filter(
|
|
250
|
-
(o) => !o.disabled && foldForSearch(o.label).includes(foldForSearch(query))
|
|
250
|
+
(o) => !o.disabled && foldForSearch(o.keywords ? `${o.label} ${o.keywords}` : o.label).includes(foldForSearch(query))
|
|
251
251
|
);
|
|
252
252
|
useActiveOptionInView(listRef, open && filtered[highlightIdx] ? `${listboxId}-opt-${highlightIdx}` : void 0);
|
|
253
253
|
const selectedLabel = options.find((o) => o.value === value)?.label ?? "";
|
|
@@ -485,6 +485,24 @@ function timeZones() {
|
|
|
485
485
|
const zones = [...new Set(listed.map(canonicalTimeZone))].filter((z) => z !== "UTC").sort((a, b) => a.localeCompare(b));
|
|
486
486
|
return ["UTC", ...zones];
|
|
487
487
|
}
|
|
488
|
+
var RENAMED_CITIES = [
|
|
489
|
+
["Kolkata", ["Asia/Calcutta", "Asia/Kolkata"]],
|
|
490
|
+
["Kyiv", ["Europe/Kiev", "Europe/Kyiv"]],
|
|
491
|
+
["Ho Chi Minh City", ["Asia/Saigon", "Asia/Ho_Chi_Minh"]],
|
|
492
|
+
["Yangon", ["Asia/Rangoon", "Asia/Yangon"]],
|
|
493
|
+
["Kathmandu", ["Asia/Katmandu", "Asia/Kathmandu"]],
|
|
494
|
+
["Nuuk", ["America/Godthab", "America/Nuuk"]],
|
|
495
|
+
["Faroe", ["Atlantic/Faeroe", "Atlantic/Faroe"]],
|
|
496
|
+
["Chuuk", ["Pacific/Truk", "Pacific/Chuuk"]],
|
|
497
|
+
["Pohnpei", ["Pacific/Ponape", "Pacific/Pohnpei"]],
|
|
498
|
+
["Kanton", ["Pacific/Enderbury", "Pacific/Kanton"]],
|
|
499
|
+
["Asmara", ["Africa/Asmera", "Africa/Asmara"]],
|
|
500
|
+
["Atikokan", ["America/Coral_Harbour", "America/Atikokan"]],
|
|
501
|
+
["Thimphu", ["Asia/Thimbu", "Asia/Thimphu"]],
|
|
502
|
+
["Dhaka", ["Asia/Dacca", "Asia/Dhaka"]],
|
|
503
|
+
["Ulaanbaatar", ["Asia/Ulan_Bator", "Asia/Ulaanbaatar"]]
|
|
504
|
+
];
|
|
505
|
+
var CITY_OF = new Map(RENAMED_CITIES.flatMap(([city, zones]) => zones.map((zone) => [zone, city])));
|
|
488
506
|
var labelOf = (zone, at) => {
|
|
489
507
|
const offset = timeZoneOffset(zone, at);
|
|
490
508
|
return offset ? `${zone.replace(/_/g, " ")} (${offset})` : zone.replace(/_/g, " ");
|
|
@@ -495,7 +513,7 @@ function zoneOptions() {
|
|
|
495
513
|
const now = Date.now();
|
|
496
514
|
if (!zoneList || now - zoneList.at > HOUR) {
|
|
497
515
|
const at = new Date(now);
|
|
498
|
-
zoneList = { at: now, options: timeZones().map((zone) => ({ value: zone, label: labelOf(zone, at) })) };
|
|
516
|
+
zoneList = { at: now, options: timeZones().map((zone) => ({ value: zone, label: labelOf(zone, at), keywords: CITY_OF.get(zone) })) };
|
|
499
517
|
}
|
|
500
518
|
return zoneList.options;
|
|
501
519
|
}
|
|
@@ -506,9 +524,9 @@ function TimezoneSelect({ value, onChange, placeholder = "Search time zones\u202
|
|
|
506
524
|
if (!stored) {
|
|
507
525
|
const mine = browserTimeZone();
|
|
508
526
|
const label = zones.find((o) => o.value === mine)?.label ?? labelOf(mine, /* @__PURE__ */ new Date());
|
|
509
|
-
return [{ value: mine, label: `${label} \xB7 your time zone
|
|
527
|
+
return [{ value: mine, label: `${label} \xB7 your time zone`, keywords: CITY_OF.get(mine) }, ...zones.filter((o) => o.value !== mine)];
|
|
510
528
|
}
|
|
511
|
-
return zones.some((o) => o.value === stored) ? zones : [{ value: stored, label: labelOf(stored, /* @__PURE__ */ new Date()) }, ...zones];
|
|
529
|
+
return zones.some((o) => o.value === stored) ? zones : [{ value: stored, label: labelOf(stored, /* @__PURE__ */ new Date()), keywords: CITY_OF.get(stored) }, ...zones];
|
|
512
530
|
}, [zones, stored]);
|
|
513
531
|
return /* @__PURE__ */ jsx(Combobox, { value: stored, onChange, options, placeholder, ...rest });
|
|
514
532
|
}
|
|
@@ -877,6 +895,279 @@ function dateSegments(dayFirst, daysInMonth = 31) {
|
|
|
877
895
|
const year = { key: "year", label: "Year", min: 1, max: 9999, maxDigits: 4, placeholder: "yyyy" };
|
|
878
896
|
return dayFirst ? [day, month, year] : [month, day, year];
|
|
879
897
|
}
|
|
898
|
+
|
|
899
|
+
// ../../showcase/src/components/Calendar/calendar-utils.ts
|
|
900
|
+
var formatters = /* @__PURE__ */ new Map();
|
|
901
|
+
function dtf(options) {
|
|
902
|
+
const locale = formatLocale();
|
|
903
|
+
const key = `${locale ?? ""}|${JSON.stringify(options)}`;
|
|
904
|
+
let f = formatters.get(key);
|
|
905
|
+
if (!f) {
|
|
906
|
+
f = new Intl.DateTimeFormat(locale, options);
|
|
907
|
+
formatters.set(key, f);
|
|
908
|
+
}
|
|
909
|
+
return f;
|
|
910
|
+
}
|
|
911
|
+
function monthName(month, width = "long") {
|
|
912
|
+
return dtf({ month: width }).format(new Date(2026, month, 1));
|
|
913
|
+
}
|
|
914
|
+
function weekdayNames(weekStartsOn, width = "short") {
|
|
915
|
+
const f = dtf({ weekday: width });
|
|
916
|
+
return Array.from({ length: 7 }, (_, i) => f.format(new Date(2026, 0, 4 + weekStartsOn + i)));
|
|
917
|
+
}
|
|
918
|
+
function isSameDay(a, b) {
|
|
919
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
920
|
+
}
|
|
921
|
+
function isSameMonth(a, b) {
|
|
922
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();
|
|
923
|
+
}
|
|
924
|
+
function isToday(d) {
|
|
925
|
+
return isSameDay(d, /* @__PURE__ */ new Date());
|
|
926
|
+
}
|
|
927
|
+
function isWeekend(d) {
|
|
928
|
+
const day = d.getDay();
|
|
929
|
+
return day === 0 || day === 6;
|
|
930
|
+
}
|
|
931
|
+
function startOfDay(d) {
|
|
932
|
+
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
933
|
+
}
|
|
934
|
+
function startOfWeek(d, weekStartsOn = 0) {
|
|
935
|
+
const date = new Date(d);
|
|
936
|
+
const day = date.getDay();
|
|
937
|
+
const diff = (day - weekStartsOn + 7) % 7;
|
|
938
|
+
date.setDate(date.getDate() - diff);
|
|
939
|
+
return startOfDay(date);
|
|
940
|
+
}
|
|
941
|
+
function endOfWeek(d, weekStartsOn = 0) {
|
|
942
|
+
const start = startOfWeek(d, weekStartsOn);
|
|
943
|
+
const end = new Date(start);
|
|
944
|
+
end.setDate(end.getDate() + 6);
|
|
945
|
+
end.setHours(23, 59, 59, 999);
|
|
946
|
+
return end;
|
|
947
|
+
}
|
|
948
|
+
function addDays2(d, n) {
|
|
949
|
+
const result = new Date(d);
|
|
950
|
+
result.setDate(result.getDate() + n);
|
|
951
|
+
return result;
|
|
952
|
+
}
|
|
953
|
+
function addMonths(d, n) {
|
|
954
|
+
const result = new Date(d);
|
|
955
|
+
const day = result.getDate();
|
|
956
|
+
result.setDate(1);
|
|
957
|
+
result.setMonth(result.getMonth() + n);
|
|
958
|
+
result.setDate(Math.min(day, new Date(result.getFullYear(), result.getMonth() + 1, 0).getDate()));
|
|
959
|
+
return result;
|
|
960
|
+
}
|
|
961
|
+
function getMonthGrid(year, month, weekStartsOn = 0) {
|
|
962
|
+
const firstOfMonth = new Date(year, month, 1);
|
|
963
|
+
const gridStart = startOfWeek(firstOfMonth, weekStartsOn);
|
|
964
|
+
const weeks = [];
|
|
965
|
+
const current = new Date(gridStart);
|
|
966
|
+
for (let w = 0; w < 6; w++) {
|
|
967
|
+
const week = [];
|
|
968
|
+
for (let d = 0; d < 7; d++) {
|
|
969
|
+
week.push(new Date(current));
|
|
970
|
+
current.setDate(current.getDate() + 1);
|
|
971
|
+
}
|
|
972
|
+
weeks.push(week);
|
|
973
|
+
}
|
|
974
|
+
return weeks;
|
|
975
|
+
}
|
|
976
|
+
function getWeekDays(date, weekStartsOn = 0) {
|
|
977
|
+
const start = startOfWeek(date, weekStartsOn);
|
|
978
|
+
const days = [];
|
|
979
|
+
for (let i = 0; i < 7; i++) {
|
|
980
|
+
days.push(addDays2(start, i));
|
|
981
|
+
}
|
|
982
|
+
return days;
|
|
983
|
+
}
|
|
984
|
+
var DAY_MS = 864e5;
|
|
985
|
+
function daysBetween(a, b) {
|
|
986
|
+
return Math.round((startOfDay(b).getTime() - startOfDay(a).getTime()) / DAY_MS);
|
|
987
|
+
}
|
|
988
|
+
function eventSpan(e) {
|
|
989
|
+
const first = startOfDay(e.start);
|
|
990
|
+
if (!e.end) return { first, last: first };
|
|
991
|
+
const lastInstant = e.allDay ? e.end : new Date(e.end.getTime() - 1);
|
|
992
|
+
const last = startOfDay(lastInstant);
|
|
993
|
+
return { first, last: last < first ? first : last };
|
|
994
|
+
}
|
|
995
|
+
function isBarEvent(e) {
|
|
996
|
+
if (e.allDay) return true;
|
|
997
|
+
if (!e.end) return false;
|
|
998
|
+
const dayLater = new Date(e.start);
|
|
999
|
+
dayLater.setDate(dayLater.getDate() + 1);
|
|
1000
|
+
return e.end.getTime() >= dayLater.getTime();
|
|
1001
|
+
}
|
|
1002
|
+
function getEventsForDay(events, date) {
|
|
1003
|
+
const day = startOfDay(date).getTime();
|
|
1004
|
+
return events.filter((e) => {
|
|
1005
|
+
const { first, last } = eventSpan(e);
|
|
1006
|
+
return first.getTime() <= day && day <= last.getTime();
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
1009
|
+
function dayPieces(events, date) {
|
|
1010
|
+
const dayStart = startOfDay(date);
|
|
1011
|
+
const next = new Date(dayStart.getFullYear(), dayStart.getMonth(), dayStart.getDate() + 1);
|
|
1012
|
+
const pieces = [];
|
|
1013
|
+
for (const event of events) {
|
|
1014
|
+
if (isBarEvent(event)) continue;
|
|
1015
|
+
const ownDayEnd = new Date(event.start.getFullYear(), event.start.getMonth(), event.start.getDate() + 1);
|
|
1016
|
+
const end = event.end && event.end > event.start ? event.end : new Date(Math.min(event.start.getTime() + 36e5, ownDayEnd.getTime()));
|
|
1017
|
+
const start = event.start < dayStart ? dayStart : event.start;
|
|
1018
|
+
const stop = end > next ? next : end;
|
|
1019
|
+
if (stop > start) pieces.push({ event, start, end: stop });
|
|
1020
|
+
}
|
|
1021
|
+
return pieces.sort((a, b) => a.start.getTime() - b.start.getTime() || b.end.getTime() - a.end.getTime());
|
|
1022
|
+
}
|
|
1023
|
+
function twelveHour() {
|
|
1024
|
+
return /^h1[12]$/.test(dtf({ hour: "numeric" }).resolvedOptions().hourCycle ?? "");
|
|
1025
|
+
}
|
|
1026
|
+
var timeOptions = () => ({ hour: twelveHour() ? "numeric" : "2-digit", minute: "2-digit" });
|
|
1027
|
+
function formatTime(d) {
|
|
1028
|
+
return dtf(timeOptions()).format(d);
|
|
1029
|
+
}
|
|
1030
|
+
function formatHourLabel(hour) {
|
|
1031
|
+
const at = new Date(2026, 0, 5, hour);
|
|
1032
|
+
return twelveHour() ? dtf({ hour: "numeric" }).format(at) : dtf({ hour: "2-digit", minute: "2-digit" }).format(at);
|
|
1033
|
+
}
|
|
1034
|
+
function dayOffset(days) {
|
|
1035
|
+
return new Intl.NumberFormat(formatLocale(), { signDisplay: "always" }).format(days);
|
|
1036
|
+
}
|
|
1037
|
+
function formatTimeRange(start, end) {
|
|
1038
|
+
if (!end) return formatTime(start);
|
|
1039
|
+
const f = dtf(timeOptions());
|
|
1040
|
+
if (daysBetween(start, end) === 0) return f.formatRange(start, end);
|
|
1041
|
+
const sep = f.formatRangeToParts(start, end).find((p) => p.source === "shared" && p.type === "literal")?.value ?? " \u2013 ";
|
|
1042
|
+
const days = endDays(start, end);
|
|
1043
|
+
return days === 0 ? `${f.format(start)}${sep}${f.format(end)}` : `${f.format(start)}${sep}${f.format(end)} (${dayOffset(days)})`;
|
|
1044
|
+
}
|
|
1045
|
+
function endDays(start, end) {
|
|
1046
|
+
return end > start ? daysBetween(start, new Date(end.getTime() - 1)) : daysBetween(start, end);
|
|
1047
|
+
}
|
|
1048
|
+
function speakTimeRange(start, end) {
|
|
1049
|
+
if (!end) return formatTime(start);
|
|
1050
|
+
const days = endDays(start, end);
|
|
1051
|
+
const to = `${formatTime(start)} to ${formatTime(end)}`;
|
|
1052
|
+
return days === 0 ? to : days === 1 ? `${to} the next day` : `${to}, ${days} days later`;
|
|
1053
|
+
}
|
|
1054
|
+
function formatMonthYear(d) {
|
|
1055
|
+
return dtf({ month: "long", year: "numeric" }).format(d);
|
|
1056
|
+
}
|
|
1057
|
+
function formatDayLong(d) {
|
|
1058
|
+
return dtf({ weekday: "long", day: "numeric", month: "long", year: "numeric" }).format(d);
|
|
1059
|
+
}
|
|
1060
|
+
function formatDayShort(d) {
|
|
1061
|
+
return dtf({ weekday: "short", day: "numeric", month: "short" }).format(d);
|
|
1062
|
+
}
|
|
1063
|
+
function formatDayMedium(d) {
|
|
1064
|
+
return dtf({ day: "numeric", month: "short", year: "numeric" }).format(d);
|
|
1065
|
+
}
|
|
1066
|
+
function formatDayRange(start, end) {
|
|
1067
|
+
return dtf({ day: "numeric", month: "short", year: "numeric" }).formatRange(startOfDay(start), startOfDay(end));
|
|
1068
|
+
}
|
|
1069
|
+
function formatMonthRange(start, end) {
|
|
1070
|
+
return dtf({ month: "long", year: "numeric" }).formatRange(new Date(start.getFullYear(), start.getMonth(), 1), new Date(end.getFullYear(), end.getMonth(), 1));
|
|
1071
|
+
}
|
|
1072
|
+
function formatWeekRange(d, weekStartsOn = 0) {
|
|
1073
|
+
return dtf({ day: "numeric", month: "short", year: "numeric" }).formatRange(startOfWeek(d, weekStartsOn), startOfDay(endOfWeek(d, weekStartsOn)));
|
|
1074
|
+
}
|
|
1075
|
+
function formatEventWhen(e, spoken = false) {
|
|
1076
|
+
const { first, last } = eventSpan(e);
|
|
1077
|
+
const multiDay = last > first;
|
|
1078
|
+
if (e.allDay) {
|
|
1079
|
+
if (!multiDay) return spoken ? formatDayLong(first) : formatDayShort(first);
|
|
1080
|
+
return dtf(spoken ? { weekday: "long", day: "numeric", month: "long" } : { day: "numeric", month: "short" }).formatRange(first, last);
|
|
1081
|
+
}
|
|
1082
|
+
if (!e.end || !isBarEvent(e)) {
|
|
1083
|
+
const day = spoken ? formatDayLong(e.start) : formatDayShort(e.start);
|
|
1084
|
+
const end = e.end && e.end > e.start ? e.end : void 0;
|
|
1085
|
+
return `${day}, ${spoken ? speakTimeRange(e.start, end) : formatTimeRange(e.start, end)}`;
|
|
1086
|
+
}
|
|
1087
|
+
return dtf({ weekday: "short", day: "numeric", month: "short", hour: "numeric", minute: "2-digit" }).formatRange(e.start, e.end);
|
|
1088
|
+
}
|
|
1089
|
+
function layoutWeek(events, days, capacity) {
|
|
1090
|
+
const weekStart = startOfDay(days[0]);
|
|
1091
|
+
const weekEnd = startOfDay(days[days.length - 1]);
|
|
1092
|
+
const items = [];
|
|
1093
|
+
for (const event of events) {
|
|
1094
|
+
const { first, last } = eventSpan(event);
|
|
1095
|
+
if (last < weekStart || first > weekEnd) continue;
|
|
1096
|
+
items.push({
|
|
1097
|
+
event,
|
|
1098
|
+
startCol: Math.max(0, daysBetween(weekStart, first)),
|
|
1099
|
+
endCol: Math.min(days.length - 1, daysBetween(weekStart, last)),
|
|
1100
|
+
before: first < weekStart,
|
|
1101
|
+
after: last > weekEnd,
|
|
1102
|
+
length: daysBetween(first, last) + 1
|
|
1103
|
+
});
|
|
1104
|
+
}
|
|
1105
|
+
items.sort((a, b) => {
|
|
1106
|
+
const barA = isBarEvent(a.event) || a.length > 1, barB = isBarEvent(b.event) || b.length > 1;
|
|
1107
|
+
if (barA !== barB) return barA ? -1 : 1;
|
|
1108
|
+
if (barA && a.length !== b.length) return b.length - a.length;
|
|
1109
|
+
return a.event.start.getTime() - b.event.start.getTime() || a.event.title.localeCompare(b.event.title);
|
|
1110
|
+
});
|
|
1111
|
+
const taken = [];
|
|
1112
|
+
const laneOf = /* @__PURE__ */ new Map();
|
|
1113
|
+
for (const item of items) {
|
|
1114
|
+
let lane = 0;
|
|
1115
|
+
while (Array.from({ length: item.endCol - item.startCol + 1 }, (_, k) => taken[lane]?.[item.startCol + k]).some(Boolean)) lane++;
|
|
1116
|
+
taken[lane] ??= [];
|
|
1117
|
+
for (let c = item.startCol; c <= item.endCol; c++) taken[lane][c] = true;
|
|
1118
|
+
laneOf.set(item, lane);
|
|
1119
|
+
}
|
|
1120
|
+
const cap = Math.max(1, capacity);
|
|
1121
|
+
const overflow = days.map((_, c) => items.some((it) => laneOf.get(it) >= cap && it.startCol <= c && c <= it.endCol));
|
|
1122
|
+
const more = days.map((_, c) => overflow[c] ? items.filter((it) => laneOf.get(it) >= cap - 1 && it.startCol <= c && c <= it.endCol).map((it) => it.event) : []);
|
|
1123
|
+
const segments = [];
|
|
1124
|
+
for (const item of items) {
|
|
1125
|
+
const lane = laneOf.get(item);
|
|
1126
|
+
if (lane >= cap) continue;
|
|
1127
|
+
if (lane < cap - 1) {
|
|
1128
|
+
segments.push({ event: item.event, startCol: item.startCol, span: item.endCol - item.startCol + 1, lane, continuesBefore: item.before, continuesAfter: item.after });
|
|
1129
|
+
continue;
|
|
1130
|
+
}
|
|
1131
|
+
let runStart = -1;
|
|
1132
|
+
for (let c = item.startCol; c <= item.endCol + 1; c++) {
|
|
1133
|
+
const free = c <= item.endCol && !overflow[c];
|
|
1134
|
+
if (free && runStart < 0) runStart = c;
|
|
1135
|
+
if (!free && runStart >= 0) {
|
|
1136
|
+
segments.push({ event: item.event, startCol: runStart, span: c - runStart, lane, continuesBefore: runStart > item.startCol || item.before, continuesAfter: c - 1 < item.endCol || item.after });
|
|
1137
|
+
runStart = -1;
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
const lanes = Math.min(cap, taken.length);
|
|
1142
|
+
return { segments, more, lanes };
|
|
1143
|
+
}
|
|
1144
|
+
function layoutPieces(pieces, minMinutes = 0) {
|
|
1145
|
+
const out = [];
|
|
1146
|
+
let group = [];
|
|
1147
|
+
let columnEnds = [];
|
|
1148
|
+
let groupEnd = -Infinity;
|
|
1149
|
+
const close = () => {
|
|
1150
|
+
for (const placed of group) placed.columns = columnEnds.length;
|
|
1151
|
+
out.push(...group);
|
|
1152
|
+
group = [];
|
|
1153
|
+
columnEnds = [];
|
|
1154
|
+
};
|
|
1155
|
+
for (const piece of pieces) {
|
|
1156
|
+
const at = piece.start.getTime();
|
|
1157
|
+
const end = Math.max(piece.end.getTime(), at + minMinutes * 6e4);
|
|
1158
|
+
if (group.length && at >= groupEnd) close();
|
|
1159
|
+
let column = columnEnds.findIndex((e) => e <= at);
|
|
1160
|
+
if (column < 0) column = columnEnds.push(0) - 1;
|
|
1161
|
+
columnEnds[column] = end;
|
|
1162
|
+
groupEnd = Math.max(group.length ? groupEnd : -Infinity, end);
|
|
1163
|
+
group.push({ piece, column, columns: 0 });
|
|
1164
|
+
}
|
|
1165
|
+
if (group.length) close();
|
|
1166
|
+
return out;
|
|
1167
|
+
}
|
|
1168
|
+
function timeToFraction(d) {
|
|
1169
|
+
return (d.getHours() * 60 + d.getMinutes()) / (24 * 60);
|
|
1170
|
+
}
|
|
880
1171
|
var CONTROL_HEIGHT2 = {
|
|
881
1172
|
sm: "h-[var(--ds-control-height-sm)]",
|
|
882
1173
|
md: "h-[var(--ds-control-height-md)]",
|
|
@@ -887,21 +1178,19 @@ var TEXT_SIZE2 = {
|
|
|
887
1178
|
md: "text-sm",
|
|
888
1179
|
lg: "text-base"
|
|
889
1180
|
};
|
|
890
|
-
var
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
"
|
|
894
|
-
"
|
|
895
|
-
"
|
|
896
|
-
"
|
|
897
|
-
"
|
|
898
|
-
"
|
|
899
|
-
"
|
|
900
|
-
"
|
|
901
|
-
"
|
|
902
|
-
"
|
|
903
|
-
"November",
|
|
904
|
-
"December"
|
|
1181
|
+
var ENGLISH_MONTHS = [
|
|
1182
|
+
"january",
|
|
1183
|
+
"february",
|
|
1184
|
+
"march",
|
|
1185
|
+
"april",
|
|
1186
|
+
"may",
|
|
1187
|
+
"june",
|
|
1188
|
+
"july",
|
|
1189
|
+
"august",
|
|
1190
|
+
"september",
|
|
1191
|
+
"october",
|
|
1192
|
+
"november",
|
|
1193
|
+
"december"
|
|
905
1194
|
];
|
|
906
1195
|
function getDaysInMonth(year, month) {
|
|
907
1196
|
return new Date(year, month + 1, 0).getDate();
|
|
@@ -909,12 +1198,9 @@ function getDaysInMonth(year, month) {
|
|
|
909
1198
|
function getFirstDayOfWeek(year, month) {
|
|
910
1199
|
return new Date(year, month, 1).getDay();
|
|
911
1200
|
}
|
|
912
|
-
function
|
|
1201
|
+
function isSameDay2(a, b) {
|
|
913
1202
|
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
914
1203
|
}
|
|
915
|
-
function formatDate(d) {
|
|
916
|
-
return `${MONTHS[d.getMonth()].slice(0, 3)} ${d.getDate()}, ${d.getFullYear()}`;
|
|
917
|
-
}
|
|
918
1204
|
function localeDayFirst() {
|
|
919
1205
|
try {
|
|
920
1206
|
const parts = new Intl.DateTimeFormat(formatLocale()).formatToParts(new Date(2e3, 11, 25));
|
|
@@ -923,23 +1209,32 @@ function localeDayFirst() {
|
|
|
923
1209
|
return true;
|
|
924
1210
|
}
|
|
925
1211
|
}
|
|
926
|
-
function validDate(year,
|
|
927
|
-
if (
|
|
928
|
-
const d = new Date(year,
|
|
929
|
-
return d.getFullYear() === year && d.getMonth() ===
|
|
1212
|
+
function validDate(year, monthIndex2, day) {
|
|
1213
|
+
if (monthIndex2 < 0 || monthIndex2 > 11 || day < 1) return null;
|
|
1214
|
+
const d = new Date(year, monthIndex2, day);
|
|
1215
|
+
return d.getFullYear() === year && d.getMonth() === monthIndex2 && d.getDate() === day ? d : null;
|
|
1216
|
+
}
|
|
1217
|
+
function monthIndex(name) {
|
|
1218
|
+
const typed = name.toLocaleLowerCase().replace(/\.$/, "");
|
|
1219
|
+
const fold = (m) => m.toLocaleLowerCase().replace(/\.$/, "");
|
|
1220
|
+
const lists = [ENGLISH_MONTHS, Array.from({ length: 12 }, (_, i) => fold(monthName(i, "long"))), Array.from({ length: 12 }, (_, i) => fold(monthName(i, "short")))];
|
|
1221
|
+
for (const list of lists) {
|
|
1222
|
+
const i = list.findIndex((m) => m.startsWith(typed) || typed.length >= 3 && typed.startsWith(m));
|
|
1223
|
+
if (i >= 0) return i;
|
|
1224
|
+
}
|
|
1225
|
+
return -1;
|
|
930
1226
|
}
|
|
931
1227
|
function parseTypedDate(text, dayFirst = localeDayFirst()) {
|
|
932
1228
|
const t = text.trim().replace(/\s+/g, " ");
|
|
933
1229
|
if (!t) return null;
|
|
934
1230
|
let m = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(t);
|
|
935
1231
|
if (m) return validDate(Number(m[1]), Number(m[2]) - 1, Number(m[3]));
|
|
936
|
-
|
|
937
|
-
m = /^([A-Za-z]{3,})\.?\s+(\d{1,2}),?\s+(\d{4})$/.exec(t);
|
|
1232
|
+
m = /^(\p{L}{3,})\.?\s+(\d{1,2}),?\s+(\d{4})$/u.exec(t);
|
|
938
1233
|
if (m) {
|
|
939
1234
|
const mi = monthIndex(m[1]);
|
|
940
1235
|
return mi < 0 ? null : validDate(Number(m[3]), mi, Number(m[2]));
|
|
941
1236
|
}
|
|
942
|
-
m = /^(\d{1,2})
|
|
1237
|
+
m = /^(\d{1,2})\.?\s+(\p{L}{3,})\.?,?\s+(\d{4})$/u.exec(t);
|
|
943
1238
|
if (m) {
|
|
944
1239
|
const mi = monthIndex(m[2]);
|
|
945
1240
|
return mi < 0 ? null : validDate(Number(m[3]), mi, Number(m[1]));
|
|
@@ -1059,7 +1354,7 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1059
1354
|
const d = validDate(next.year, next.month - 1, next.day);
|
|
1060
1355
|
const ok = !!d && (!min || d >= min) && (!max || d <= max);
|
|
1061
1356
|
setTypedInvalid(!ok);
|
|
1062
|
-
if (d && ok && !(value &&
|
|
1357
|
+
if (d && ok && !(value && isSameDay2(value, d))) {
|
|
1063
1358
|
lastCommitted.current = d.getTime();
|
|
1064
1359
|
onChange(d);
|
|
1065
1360
|
setViewDate(d);
|
|
@@ -1139,7 +1434,7 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1139
1434
|
};
|
|
1140
1435
|
const rangeA = range2?.start ?? null;
|
|
1141
1436
|
const rangeB = range2?.end ?? null;
|
|
1142
|
-
const otherEnd = value ? rangeA && !
|
|
1437
|
+
const otherEnd = value ? rangeA && !isSameDay2(rangeA, value) ? rangeA : rangeB : rangeA ?? rangeB;
|
|
1143
1438
|
const thisEnd = value ?? (otherEnd && hover ? hover : null);
|
|
1144
1439
|
const [bandStart, bandEnd] = otherEnd && thisEnd ? otherEnd <= thisEnd ? [otherEnd, thisEnd] : [thisEnd, otherEnd] : [null, null];
|
|
1145
1440
|
const inBand = (d) => !!(bandStart && bandEnd && d > bandStart && d < bandEnd);
|
|
@@ -1256,11 +1551,7 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1256
1551
|
style: { padding: "var(--ds-space-2) var(--ds-space-3)" },
|
|
1257
1552
|
children: [
|
|
1258
1553
|
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: prevMonth, "aria-label": "Previous month", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14, className: "rotate-180" }) }),
|
|
1259
|
-
/* @__PURE__ */
|
|
1260
|
-
MONTHS[month],
|
|
1261
|
-
" ",
|
|
1262
|
-
year
|
|
1263
|
-
] }),
|
|
1554
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-[var(--ds-text-primary)]", children: formatMonthYear(viewDate) }),
|
|
1264
1555
|
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: nextMonth, "aria-label": "Next month", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14 }) })
|
|
1265
1556
|
]
|
|
1266
1557
|
}
|
|
@@ -1270,18 +1561,18 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1270
1561
|
{
|
|
1271
1562
|
ref: gridRef,
|
|
1272
1563
|
role: "grid",
|
|
1273
|
-
"aria-label":
|
|
1564
|
+
"aria-label": formatMonthYear(viewDate),
|
|
1274
1565
|
onKeyDown: grid.onKeyDown,
|
|
1275
1566
|
className: "flex flex-col gap-ds-0.5 tabular-nums",
|
|
1276
1567
|
style: { padding: "var(--ds-space-2) var(--ds-space-3)" },
|
|
1277
1568
|
children: [
|
|
1278
|
-
/* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 gap-ds-0.5 mb-ds-0.5", children:
|
|
1569
|
+
/* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 gap-ds-0.5 mb-ds-0.5", children: weekdayNames(0, "narrow").map((d, i) => /* @__PURE__ */ jsx("div", { role: "columnheader", "aria-label": weekdayNames(0, "long")[i], className: "text-center text-2xs font-medium text-[var(--ds-text-muted)] py-ds-1", children: d }, i)) }),
|
|
1279
1570
|
weeks.map((week, w) => /* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 gap-ds-0.5", onMouseLeave: () => setHover(null), children: week.map((day, i) => {
|
|
1280
1571
|
if (day === null) return /* @__PURE__ */ jsx("div", { role: "gridcell" }, `empty-${i}`);
|
|
1281
1572
|
const dateObj = new Date(year, month, day);
|
|
1282
|
-
const isSelected = !!value &&
|
|
1283
|
-
const isOtherEnd = !!otherEnd &&
|
|
1284
|
-
const isToday2 =
|
|
1573
|
+
const isSelected = !!value && isSameDay2(dateObj, value);
|
|
1574
|
+
const isOtherEnd = !!otherEnd && isSameDay2(dateObj, otherEnd);
|
|
1575
|
+
const isToday2 = isSameDay2(dateObj, today);
|
|
1285
1576
|
const between = inBand(dateObj);
|
|
1286
1577
|
const dis = isDisabledDay(dateObj);
|
|
1287
1578
|
return /* @__PURE__ */ jsx(
|
|
@@ -1294,12 +1585,12 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1294
1585
|
"aria-disabled": dis || void 0,
|
|
1295
1586
|
onClick: () => selectDay(day),
|
|
1296
1587
|
onFocus: () => {
|
|
1297
|
-
if (!
|
|
1588
|
+
if (!isSameDay2(dateObj, focusDate)) setFocusDate(dateObj);
|
|
1298
1589
|
},
|
|
1299
1590
|
onMouseEnter: () => setHover(dateObj),
|
|
1300
1591
|
"aria-selected": isSelected,
|
|
1301
1592
|
"aria-current": isToday2 ? "date" : void 0,
|
|
1302
|
-
"aria-label":
|
|
1593
|
+
"aria-label": formatDayLong(dateObj),
|
|
1303
1594
|
className: cn(
|
|
1304
1595
|
"w-full aspect-square flex items-center justify-center text-xs",
|
|
1305
1596
|
"transition-colors cursor-pointer",
|
|
@@ -1355,174 +1646,6 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1355
1646
|
)
|
|
1356
1647
|
] });
|
|
1357
1648
|
}
|
|
1358
|
-
|
|
1359
|
-
// ../../showcase/src/components/Calendar/calendar-utils.ts
|
|
1360
|
-
var MONTH_NAMES = [
|
|
1361
|
-
"January",
|
|
1362
|
-
"February",
|
|
1363
|
-
"March",
|
|
1364
|
-
"April",
|
|
1365
|
-
"May",
|
|
1366
|
-
"June",
|
|
1367
|
-
"July",
|
|
1368
|
-
"August",
|
|
1369
|
-
"September",
|
|
1370
|
-
"October",
|
|
1371
|
-
"November",
|
|
1372
|
-
"December"
|
|
1373
|
-
];
|
|
1374
|
-
var MONTH_NAMES_SHORT = [
|
|
1375
|
-
"Jan",
|
|
1376
|
-
"Feb",
|
|
1377
|
-
"Mar",
|
|
1378
|
-
"Apr",
|
|
1379
|
-
"May",
|
|
1380
|
-
"Jun",
|
|
1381
|
-
"Jul",
|
|
1382
|
-
"Aug",
|
|
1383
|
-
"Sep",
|
|
1384
|
-
"Oct",
|
|
1385
|
-
"Nov",
|
|
1386
|
-
"Dec"
|
|
1387
|
-
];
|
|
1388
|
-
var DAY_NAMES_SHORT = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
1389
|
-
var DAY_NAMES_MIN = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
1390
|
-
function getOrderedDayNames(weekStartsOn) {
|
|
1391
|
-
if (weekStartsOn === 1) return [...DAY_NAMES_MIN.slice(1), DAY_NAMES_MIN[0]];
|
|
1392
|
-
return DAY_NAMES_MIN;
|
|
1393
|
-
}
|
|
1394
|
-
function getOrderedDayNamesShort(weekStartsOn) {
|
|
1395
|
-
if (weekStartsOn === 1) return [...DAY_NAMES_SHORT.slice(1), DAY_NAMES_SHORT[0]];
|
|
1396
|
-
return DAY_NAMES_SHORT;
|
|
1397
|
-
}
|
|
1398
|
-
function isSameDay2(a, b) {
|
|
1399
|
-
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
1400
|
-
}
|
|
1401
|
-
function isSameMonth(a, b) {
|
|
1402
|
-
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();
|
|
1403
|
-
}
|
|
1404
|
-
function isToday(d) {
|
|
1405
|
-
return isSameDay2(d, /* @__PURE__ */ new Date());
|
|
1406
|
-
}
|
|
1407
|
-
function isWeekend(d) {
|
|
1408
|
-
const day = d.getDay();
|
|
1409
|
-
return day === 0 || day === 6;
|
|
1410
|
-
}
|
|
1411
|
-
function startOfDay(d) {
|
|
1412
|
-
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
1413
|
-
}
|
|
1414
|
-
function startOfWeek(d, weekStartsOn = 0) {
|
|
1415
|
-
const date = new Date(d);
|
|
1416
|
-
const day = date.getDay();
|
|
1417
|
-
const diff = (day - weekStartsOn + 7) % 7;
|
|
1418
|
-
date.setDate(date.getDate() - diff);
|
|
1419
|
-
return startOfDay(date);
|
|
1420
|
-
}
|
|
1421
|
-
function endOfWeek(d, weekStartsOn = 0) {
|
|
1422
|
-
const start = startOfWeek(d, weekStartsOn);
|
|
1423
|
-
const end = new Date(start);
|
|
1424
|
-
end.setDate(end.getDate() + 6);
|
|
1425
|
-
end.setHours(23, 59, 59, 999);
|
|
1426
|
-
return end;
|
|
1427
|
-
}
|
|
1428
|
-
function addDays2(d, n) {
|
|
1429
|
-
const result = new Date(d);
|
|
1430
|
-
result.setDate(result.getDate() + n);
|
|
1431
|
-
return result;
|
|
1432
|
-
}
|
|
1433
|
-
function addMonths(d, n) {
|
|
1434
|
-
const result = new Date(d);
|
|
1435
|
-
result.setMonth(result.getMonth() + n);
|
|
1436
|
-
return result;
|
|
1437
|
-
}
|
|
1438
|
-
function getMonthGrid(year, month, weekStartsOn = 0) {
|
|
1439
|
-
const firstOfMonth = new Date(year, month, 1);
|
|
1440
|
-
const gridStart = startOfWeek(firstOfMonth, weekStartsOn);
|
|
1441
|
-
const weeks = [];
|
|
1442
|
-
const current = new Date(gridStart);
|
|
1443
|
-
for (let w = 0; w < 6; w++) {
|
|
1444
|
-
const week = [];
|
|
1445
|
-
for (let d = 0; d < 7; d++) {
|
|
1446
|
-
week.push(new Date(current));
|
|
1447
|
-
current.setDate(current.getDate() + 1);
|
|
1448
|
-
}
|
|
1449
|
-
weeks.push(week);
|
|
1450
|
-
}
|
|
1451
|
-
return weeks;
|
|
1452
|
-
}
|
|
1453
|
-
function getWeekDays(date, weekStartsOn = 0) {
|
|
1454
|
-
const start = startOfWeek(date, weekStartsOn);
|
|
1455
|
-
const days = [];
|
|
1456
|
-
for (let i = 0; i < 7; i++) {
|
|
1457
|
-
days.push(addDays2(start, i));
|
|
1458
|
-
}
|
|
1459
|
-
return days;
|
|
1460
|
-
}
|
|
1461
|
-
function getEventsForDay(events, date) {
|
|
1462
|
-
const dayStart = startOfDay(date);
|
|
1463
|
-
const dayEnd = new Date(dayStart);
|
|
1464
|
-
dayEnd.setHours(23, 59, 59, 999);
|
|
1465
|
-
return events.filter((e) => {
|
|
1466
|
-
const eStart = new Date(e.start);
|
|
1467
|
-
const eEnd = e.end ? new Date(e.end) : eStart;
|
|
1468
|
-
return eStart <= dayEnd && eEnd >= dayStart;
|
|
1469
|
-
});
|
|
1470
|
-
}
|
|
1471
|
-
function formatTime(d) {
|
|
1472
|
-
const h = d.getHours();
|
|
1473
|
-
const m = d.getMinutes();
|
|
1474
|
-
const ampm = h >= 12 ? "PM" : "AM";
|
|
1475
|
-
const hour = h % 12 || 12;
|
|
1476
|
-
return m === 0 ? `${hour} ${ampm}` : `${hour}:${String(m).padStart(2, "0")} ${ampm}`;
|
|
1477
|
-
}
|
|
1478
|
-
function formatTimeRange(start, end) {
|
|
1479
|
-
if (!end) return formatTime(start);
|
|
1480
|
-
return `${formatTime(start)} \u2013 ${formatTime(end)}`;
|
|
1481
|
-
}
|
|
1482
|
-
function formatWeekRange(d, weekStartsOn = 0) {
|
|
1483
|
-
const start = startOfWeek(d, weekStartsOn);
|
|
1484
|
-
const end = endOfWeek(d, weekStartsOn);
|
|
1485
|
-
const sameMonth = start.getMonth() === end.getMonth();
|
|
1486
|
-
if (sameMonth) {
|
|
1487
|
-
return `${MONTH_NAMES_SHORT[start.getMonth()]} ${start.getDate()} \u2013 ${end.getDate()}, ${start.getFullYear()}`;
|
|
1488
|
-
}
|
|
1489
|
-
const sameYear = start.getFullYear() === end.getFullYear();
|
|
1490
|
-
if (sameYear) {
|
|
1491
|
-
return `${MONTH_NAMES_SHORT[start.getMonth()]} ${start.getDate()} \u2013 ${MONTH_NAMES_SHORT[end.getMonth()]} ${end.getDate()}, ${start.getFullYear()}`;
|
|
1492
|
-
}
|
|
1493
|
-
return `${MONTH_NAMES_SHORT[start.getMonth()]} ${start.getDate()}, ${start.getFullYear()} \u2013 ${MONTH_NAMES_SHORT[end.getMonth()]} ${end.getDate()}, ${end.getFullYear()}`;
|
|
1494
|
-
}
|
|
1495
|
-
function getOverlappingGroups(events) {
|
|
1496
|
-
const timed = events.filter((e) => !e.allDay && e.end).sort((a, b) => a.start.getTime() - b.start.getTime());
|
|
1497
|
-
if (timed.length === 0) return [];
|
|
1498
|
-
const result = [];
|
|
1499
|
-
const columns = [];
|
|
1500
|
-
for (const event of timed) {
|
|
1501
|
-
const eStart = event.start.getTime();
|
|
1502
|
-
const eEnd = (event.end ?? event.start).getTime();
|
|
1503
|
-
let placed = false;
|
|
1504
|
-
for (let col = 0; col < columns.length; col++) {
|
|
1505
|
-
if (columns[col].end <= eStart) {
|
|
1506
|
-
columns[col].end = eEnd;
|
|
1507
|
-
result.push({ event, column: col, totalColumns: 0 });
|
|
1508
|
-
placed = true;
|
|
1509
|
-
break;
|
|
1510
|
-
}
|
|
1511
|
-
}
|
|
1512
|
-
if (!placed) {
|
|
1513
|
-
columns.push({ end: eEnd });
|
|
1514
|
-
result.push({ event, column: columns.length - 1, totalColumns: 0 });
|
|
1515
|
-
}
|
|
1516
|
-
}
|
|
1517
|
-
const totalCols = columns.length;
|
|
1518
|
-
for (const item of result) {
|
|
1519
|
-
item.totalColumns = totalCols;
|
|
1520
|
-
}
|
|
1521
|
-
return result;
|
|
1522
|
-
}
|
|
1523
|
-
function timeToFraction(d) {
|
|
1524
|
-
return (d.getHours() * 60 + d.getMinutes()) / (24 * 60);
|
|
1525
|
-
}
|
|
1526
1649
|
var CONTROL_HEIGHT3 = {
|
|
1527
1650
|
sm: "h-[var(--ds-control-height-sm)]",
|
|
1528
1651
|
md: "h-[var(--ds-control-height-md)]",
|
|
@@ -1533,10 +1656,6 @@ var TEXT_SIZE3 = {
|
|
|
1533
1656
|
md: "text-sm",
|
|
1534
1657
|
lg: "text-base"
|
|
1535
1658
|
};
|
|
1536
|
-
var MONTHS2 = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
1537
|
-
function fmt(d) {
|
|
1538
|
-
return `${MONTHS2[d.getMonth()].slice(0, 3)} ${d.getDate()}, ${d.getFullYear()}`;
|
|
1539
|
-
}
|
|
1540
1659
|
var DEFAULT_DATE_RANGE_PRESETS = [
|
|
1541
1660
|
{ label: "Today", range: () => {
|
|
1542
1661
|
const t = startOfDay(/* @__PURE__ */ new Date());
|
|
@@ -1591,7 +1710,8 @@ function DateRangePicker({
|
|
|
1591
1710
|
const labelledBy = control.labelId ? `${control.labelId} ${triggerId}` : void 0;
|
|
1592
1711
|
const pos = usePosition(triggerRef, panelRef, open, { side: "bottom", align: "start", offset: 4, flip: true });
|
|
1593
1712
|
const today = useMemo(() => startOfDay(/* @__PURE__ */ new Date()), []);
|
|
1594
|
-
const dayNames =
|
|
1713
|
+
const dayNames = weekdayNames(weekStartsOn, "narrow");
|
|
1714
|
+
const dayNamesLong = weekdayNames(weekStartsOn, "long");
|
|
1595
1715
|
const gridRef = useRef(null);
|
|
1596
1716
|
const [focusDate, setFocusDate] = useState(() => startOfDay(value.start ?? /* @__PURE__ */ new Date()));
|
|
1597
1717
|
const [prevOpen, setPrevOpen] = useState(open);
|
|
@@ -1605,8 +1725,8 @@ function DateRangePicker({
|
|
|
1605
1725
|
}
|
|
1606
1726
|
const showDay = (d) => {
|
|
1607
1727
|
setFocusDate(d);
|
|
1608
|
-
const
|
|
1609
|
-
const offset =
|
|
1728
|
+
const monthIndex2 = (x) => x.getFullYear() * 12 + x.getMonth();
|
|
1729
|
+
const offset = monthIndex2(d) - monthIndex2(viewDate);
|
|
1610
1730
|
if (offset < 0) setViewDate(new Date(d.getFullYear(), d.getMonth(), 1));
|
|
1611
1731
|
else if (offset > 1) setViewDate(new Date(d.getFullYear(), d.getMonth() - 1, 1));
|
|
1612
1732
|
};
|
|
@@ -1668,7 +1788,7 @@ function DateRangePicker({
|
|
|
1668
1788
|
const rangeEnd2 = value.end ?? previewEnd;
|
|
1669
1789
|
const inRange = (d) => !!(rangeStart && rangeEnd2 && d > rangeStart && d < rangeEnd2);
|
|
1670
1790
|
const months = [viewDate, addMonths(viewDate, 1)];
|
|
1671
|
-
const summary = value.start && value.end ?
|
|
1791
|
+
const summary = value.start && value.end ? formatDayRange(value.start, value.end) : value.start ? `${formatDayMedium(value.start)} \u2013 \u2026` : null;
|
|
1672
1792
|
return /* @__PURE__ */ jsxs("div", { ref, className: cn(className), children: [
|
|
1673
1793
|
label && /* @__PURE__ */ jsx("label", { htmlFor: triggerId, className: "block text-sm font-medium text-[var(--ds-text-primary)] mb-ds-1", children: label }),
|
|
1674
1794
|
control.requiredNote,
|
|
@@ -1735,23 +1855,15 @@ function DateRangePicker({
|
|
|
1735
1855
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
1736
1856
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between bg-[var(--ds-bg-muted)] rounded-tr-[var(--ds-radius-md)] px-ds-3 py-ds-2", children: [
|
|
1737
1857
|
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: () => pageMonths(-1), "aria-label": "Previous month", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14, className: "rotate-180" }) }),
|
|
1738
|
-
/* @__PURE__ */
|
|
1739
|
-
MONTHS2[months[0].getMonth()],
|
|
1740
|
-
" ",
|
|
1741
|
-
months[0].getFullYear(),
|
|
1742
|
-
" \u2013 ",
|
|
1743
|
-
MONTHS2[months[1].getMonth()],
|
|
1744
|
-
" ",
|
|
1745
|
-
months[1].getFullYear()
|
|
1746
|
-
] }),
|
|
1858
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-[var(--ds-text-primary)]", children: formatMonthRange(months[0], months[1]) }),
|
|
1747
1859
|
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: () => pageMonths(1), "aria-label": "Next month", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14 }) })
|
|
1748
1860
|
] }),
|
|
1749
|
-
/* @__PURE__ */ jsx("div", { ref: gridRef, onKeyDown: grid.onKeyDown, className: "flex gap-ds-4 px-ds-3 py-ds-2", onMouseLeave: () => setHover(null), children: months.map((m) => /* @__PURE__ */ jsxs("div", { role: "grid", "aria-label":
|
|
1750
|
-
/* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 gap-ds-0.5 mb-ds-0.5", children: dayNames.map((d) => /* @__PURE__ */ jsx("div", { role: "columnheader", className: "text-center text-2xs font-medium text-[var(--ds-text-muted)] py-ds-1", children: d },
|
|
1861
|
+
/* @__PURE__ */ jsx("div", { ref: gridRef, onKeyDown: grid.onKeyDown, className: "flex gap-ds-4 px-ds-3 py-ds-2", onMouseLeave: () => setHover(null), children: months.map((m) => /* @__PURE__ */ jsxs("div", { role: "grid", "aria-label": formatMonthYear(m), className: "w-[224px] flex flex-col gap-ds-0.5", children: [
|
|
1862
|
+
/* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 gap-ds-0.5 mb-ds-0.5", children: dayNames.map((d, i) => /* @__PURE__ */ jsx("div", { role: "columnheader", "aria-label": dayNamesLong[i], className: "text-center text-2xs font-medium text-[var(--ds-text-muted)] py-ds-1", children: d }, i)) }),
|
|
1751
1863
|
getMonthGrid(m.getFullYear(), m.getMonth(), weekStartsOn).map((week, w) => /* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 gap-ds-0.5", children: week.map((d) => {
|
|
1752
1864
|
if (!isSameMonth(d, m)) return /* @__PURE__ */ jsx("div", { role: "gridcell" }, d.toISOString());
|
|
1753
|
-
const isStart = !!rangeStart &&
|
|
1754
|
-
const isEnd = !!rangeEnd2 &&
|
|
1865
|
+
const isStart = !!rangeStart && isSameDay(d, rangeStart);
|
|
1866
|
+
const isEnd = !!rangeEnd2 && isSameDay(d, rangeEnd2);
|
|
1755
1867
|
const between = inRange(d);
|
|
1756
1868
|
const dis = isDisabledDay(d);
|
|
1757
1869
|
return /* @__PURE__ */ jsx(
|
|
@@ -1764,17 +1876,17 @@ function DateRangePicker({
|
|
|
1764
1876
|
"aria-disabled": dis || void 0,
|
|
1765
1877
|
onClick: () => selectDay(d),
|
|
1766
1878
|
onFocus: () => {
|
|
1767
|
-
if (!
|
|
1879
|
+
if (!isSameDay(d, focusDate)) setFocusDate(d);
|
|
1768
1880
|
},
|
|
1769
1881
|
onMouseEnter: () => setHover(d),
|
|
1770
1882
|
"aria-selected": isStart || isEnd || between,
|
|
1771
|
-
"aria-current":
|
|
1772
|
-
"aria-label":
|
|
1883
|
+
"aria-current": isSameDay(d, today) ? "date" : void 0,
|
|
1884
|
+
"aria-label": formatDayLong(d),
|
|
1773
1885
|
className: cn(
|
|
1774
1886
|
"w-full aspect-square flex items-center justify-center text-xs",
|
|
1775
1887
|
"transition-colors cursor-pointer",
|
|
1776
1888
|
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
1777
|
-
isStart || isEnd ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)] font-bold rounded-[var(--ds-radius-sm)]" : between ? "bg-[var(--ds-accent-subtle)] text-[var(--ds-accent-subtle-text)] rounded-none" :
|
|
1889
|
+
isStart || isEnd ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)] font-bold rounded-[var(--ds-radius-sm)]" : between ? "bg-[var(--ds-accent-subtle)] text-[var(--ds-accent-subtle-text)] rounded-none" : isSameDay(d, today) ? "border-[length:var(--ds-border-width)] border-[var(--ds-accent-primary)] text-[var(--ds-accent-primary)] font-medium rounded-[var(--ds-radius-sm)]" : "text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-emphasis)] rounded-[var(--ds-radius-sm)]",
|
|
1778
1890
|
dis && "opacity-disabled cursor-not-allowed hover:bg-transparent"
|
|
1779
1891
|
),
|
|
1780
1892
|
children: d.getDate()
|
|
@@ -6393,593 +6505,755 @@ function SegmentedControl({
|
|
|
6393
6505
|
}
|
|
6394
6506
|
);
|
|
6395
6507
|
}
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6400
|
-
|
|
6401
|
-
|
|
6402
|
-
|
|
6403
|
-
|
|
6404
|
-
if (
|
|
6405
|
-
const
|
|
6406
|
-
return
|
|
6407
|
-
|
|
6408
|
-
|
|
6508
|
+
|
|
6509
|
+
// ../../showcase/src/components/Calendar/event-colours.ts
|
|
6510
|
+
function eventColours(category) {
|
|
6511
|
+
const colour = category?.color;
|
|
6512
|
+
if (colour === void 0 || colour === "accent" || colour === "var(--ds-accent-primary)") return ACCENT;
|
|
6513
|
+
if (colour === "neutral") return NEUTRAL;
|
|
6514
|
+
if (typeof colour === "number") return Number.isInteger(colour) && colour >= 1 ? supporting(colour) : NEUTRAL;
|
|
6515
|
+
const named = SUPPORTING_TOKEN.exec(colour.trim());
|
|
6516
|
+
if (named) return supporting(Number(named[1]));
|
|
6517
|
+
const chart = CHART_TOKEN.exec(colour.trim());
|
|
6518
|
+
if (chart) return Number(chart[1]) === 1 ? ACCENT : supporting(Number(chart[1]) - 1);
|
|
6519
|
+
return { ...NEUTRAL, edge: colour };
|
|
6520
|
+
}
|
|
6521
|
+
var SUPPORTING_TOKEN = /^var\(\s*--ds-palette-(\d+)-[a-z-]+\s*\)$/;
|
|
6522
|
+
var CHART_TOKEN = /^var\(\s*--ds-chart-(\d+)\s*\)$/;
|
|
6523
|
+
var supporting = (n) => ({
|
|
6524
|
+
fill: `var(--ds-palette-${n}-bg, ${NEUTRAL.fill})`,
|
|
6525
|
+
text: `var(--ds-palette-${n}-text, ${NEUTRAL.text})`,
|
|
6526
|
+
edge: `var(--ds-palette-${n}-chart, ${NEUTRAL.edge})`
|
|
6527
|
+
});
|
|
6528
|
+
var ACCENT = {
|
|
6529
|
+
fill: "var(--ds-accent-bg, var(--ds-accent-subtle))",
|
|
6530
|
+
text: "var(--ds-accent-text, var(--ds-text-primary))",
|
|
6531
|
+
edge: "var(--ds-chart-1)"
|
|
6532
|
+
};
|
|
6533
|
+
var NEUTRAL = {
|
|
6534
|
+
fill: "var(--ds-bg-muted)",
|
|
6535
|
+
text: "var(--ds-text-primary)",
|
|
6536
|
+
edge: "var(--ds-input-border)"
|
|
6537
|
+
};
|
|
6538
|
+
function EventBar({ event, category, compact, onOpen, inert, showTime = true, continuesBefore, continuesAfter, className, style }) {
|
|
6539
|
+
const ref = useRef(null);
|
|
6540
|
+
const colours = eventColours(category);
|
|
6541
|
+
const name = eventName(event, category);
|
|
6542
|
+
const look = cn(
|
|
6543
|
+
"border-[length:var(--ds-border-width)] border-solid rounded-[var(--ds-radius-sm)]",
|
|
6544
|
+
continuesBefore && "rounded-s-none border-s-0",
|
|
6545
|
+
continuesAfter && "rounded-e-none border-e-0"
|
|
6546
|
+
);
|
|
6547
|
+
const paint = { backgroundColor: colours.fill, color: colours.text, borderColor: colours.edge, ...style };
|
|
6548
|
+
if (inert) {
|
|
6549
|
+
return /* @__PURE__ */ jsx(
|
|
6550
|
+
"span",
|
|
6409
6551
|
{
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
"bg-[var(--ds-bg-surface-elevated)]",
|
|
6414
|
-
"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]",
|
|
6415
|
-
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
6416
|
-
"rounded-[var(--ds-radius-md)]",
|
|
6417
|
-
"shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]",
|
|
6418
|
-
"p-ds-3 space-y-ds-2"
|
|
6419
|
-
),
|
|
6420
|
-
style: { top: pos.top, left: pos.left },
|
|
6421
|
-
role: "tooltip",
|
|
6422
|
-
children: [
|
|
6423
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-ds-2", children: [
|
|
6424
|
-
/* @__PURE__ */ jsx("p", { className: "font-[var(--ds-weight-heading)] text-sm text-[var(--ds-text-primary)] leading-snug", children: event.title }),
|
|
6425
|
-
category && /* @__PURE__ */ jsxs(Badge, { variant: "outline", size: "sm", className: "shrink-0", children: [
|
|
6426
|
-
/* @__PURE__ */ jsx(
|
|
6427
|
-
"span",
|
|
6428
|
-
{
|
|
6429
|
-
className: "inline-block w-1.5 h-1.5 rounded-[var(--ds-radius-full)] mr-ds-1",
|
|
6430
|
-
style: { backgroundColor: color }
|
|
6431
|
-
}
|
|
6432
|
-
),
|
|
6433
|
-
category.label
|
|
6434
|
-
] })
|
|
6435
|
-
] }),
|
|
6436
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-[var(--ds-text-secondary)]", children: event.allDay ? "All day" : formatTimeRange(event.start, event.end) }),
|
|
6437
|
-
event.location && /* @__PURE__ */ jsxs("p", { className: "text-xs text-[var(--ds-text-muted)] flex items-center gap-ds-1", children: [
|
|
6438
|
-
/* @__PURE__ */ jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
6439
|
-
/* @__PURE__ */ jsx("path", { d: "M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" }),
|
|
6440
|
-
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "10", r: "3" })
|
|
6441
|
-
] }),
|
|
6442
|
-
event.location
|
|
6443
|
-
] }),
|
|
6444
|
-
event.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-[var(--ds-text-muted)] line-clamp-2", children: event.description })
|
|
6445
|
-
]
|
|
6552
|
+
className: cn("block w-full text-left text-xs leading-tight px-ds-1.5 py-ds-0.5 truncate", look, className),
|
|
6553
|
+
style: paint,
|
|
6554
|
+
children: event.title
|
|
6446
6555
|
}
|
|
6447
|
-
)
|
|
6448
|
-
|
|
6449
|
-
);
|
|
6450
|
-
}
|
|
6451
|
-
function EventBar({ event, category, compact, onClick, className }) {
|
|
6452
|
-
const [hovered, setHovered] = useState(false);
|
|
6453
|
-
const barRef = useRef(null);
|
|
6454
|
-
const hoverTimeout = useRef(void 0);
|
|
6455
|
-
const color = category?.color ?? "var(--ds-accent-primary)";
|
|
6456
|
-
const handleMouseEnter = () => {
|
|
6457
|
-
hoverTimeout.current = setTimeout(() => setHovered(true), 300);
|
|
6458
|
-
};
|
|
6459
|
-
const handleMouseLeave = () => {
|
|
6460
|
-
clearTimeout(hoverTimeout.current);
|
|
6461
|
-
setHovered(false);
|
|
6462
|
-
};
|
|
6556
|
+
);
|
|
6557
|
+
}
|
|
6463
6558
|
if (compact) {
|
|
6464
6559
|
return /* @__PURE__ */ jsx(
|
|
6465
6560
|
"button",
|
|
6466
6561
|
{
|
|
6467
|
-
ref
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
|
|
6471
|
-
),
|
|
6472
|
-
style: { backgroundColor: color },
|
|
6473
|
-
onMouseEnter: handleMouseEnter,
|
|
6474
|
-
onMouseLeave: handleMouseLeave,
|
|
6562
|
+
ref,
|
|
6563
|
+
type: "button",
|
|
6564
|
+
className: cn("w-1.5 h-1.5 rounded-[var(--ds-radius-full)] shrink-0 cursor-pointer", className),
|
|
6565
|
+
style: { backgroundColor: colours.edge },
|
|
6475
6566
|
onClick: (e) => {
|
|
6476
6567
|
e.stopPropagation();
|
|
6477
|
-
|
|
6568
|
+
onOpen?.(event, e.currentTarget);
|
|
6478
6569
|
},
|
|
6479
|
-
"aria-label":
|
|
6480
|
-
children: /* @__PURE__ */ jsx(
|
|
6481
|
-
EventPopover,
|
|
6482
|
-
{
|
|
6483
|
-
event,
|
|
6484
|
-
category,
|
|
6485
|
-
open: hovered,
|
|
6486
|
-
anchorRef: barRef
|
|
6487
|
-
}
|
|
6488
|
-
)
|
|
6570
|
+
"aria-label": name
|
|
6489
6571
|
}
|
|
6490
6572
|
);
|
|
6491
6573
|
}
|
|
6492
6574
|
return /* @__PURE__ */ jsxs(
|
|
6493
6575
|
"button",
|
|
6494
6576
|
{
|
|
6495
|
-
ref
|
|
6577
|
+
ref,
|
|
6578
|
+
type: "button",
|
|
6579
|
+
"data-calendar-event": event.id,
|
|
6496
6580
|
className: cn(
|
|
6497
|
-
"w-full text-left text-xs leading-tight px-ds-1.5 py-ds-0.5
|
|
6498
|
-
|
|
6581
|
+
"w-full text-left text-xs leading-tight px-ds-1.5 py-ds-0.5",
|
|
6582
|
+
look,
|
|
6583
|
+
"truncate cursor-pointer transition-[filter] hover:brightness-95",
|
|
6499
6584
|
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
6500
6585
|
className
|
|
6501
6586
|
),
|
|
6502
|
-
style:
|
|
6503
|
-
backgroundColor: `color-mix(in oklch, ${color} 18%, transparent)`,
|
|
6504
|
-
color,
|
|
6505
|
-
borderLeft: `2px solid ${color}`
|
|
6506
|
-
},
|
|
6507
|
-
onMouseEnter: handleMouseEnter,
|
|
6508
|
-
onMouseLeave: handleMouseLeave,
|
|
6587
|
+
style: paint,
|
|
6509
6588
|
onClick: (e) => {
|
|
6510
6589
|
e.stopPropagation();
|
|
6511
|
-
|
|
6590
|
+
onOpen?.(event, e.currentTarget);
|
|
6512
6591
|
},
|
|
6513
|
-
|
|
6592
|
+
"aria-label": name,
|
|
6514
6593
|
children: [
|
|
6515
|
-
!event.allDay && /* @__PURE__ */ jsx("span", { className: "font-medium mr-ds-1
|
|
6516
|
-
event.title
|
|
6517
|
-
/* @__PURE__ */ jsx(
|
|
6518
|
-
EventPopover,
|
|
6519
|
-
{
|
|
6520
|
-
event,
|
|
6521
|
-
category,
|
|
6522
|
-
open: hovered,
|
|
6523
|
-
anchorRef: barRef
|
|
6524
|
-
}
|
|
6525
|
-
)
|
|
6594
|
+
showTime && !event.allDay && /* @__PURE__ */ jsx("span", { className: "font-medium mr-ds-1", children: formatTime(event.start) }),
|
|
6595
|
+
event.title
|
|
6526
6596
|
]
|
|
6527
6597
|
}
|
|
6528
6598
|
);
|
|
6529
6599
|
}
|
|
6530
|
-
|
|
6531
|
-
|
|
6532
|
-
|
|
6533
|
-
|
|
6534
|
-
|
|
6535
|
-
|
|
6536
|
-
|
|
6537
|
-
const
|
|
6538
|
-
const
|
|
6539
|
-
const
|
|
6540
|
-
const
|
|
6541
|
-
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
|
|
6546
|
-
|
|
6600
|
+
function eventName(event, category) {
|
|
6601
|
+
return [event.title, formatEventWhen(event, true), category?.label].filter(Boolean).join(", ");
|
|
6602
|
+
}
|
|
6603
|
+
var CALENDAR_LAYER = "data-calendar-layer";
|
|
6604
|
+
function EventCard({ event, category, anchor, actions, onClose, fallbackFocus }) {
|
|
6605
|
+
const anchorRef = useMemo(() => ({ current: anchor }), [anchor]);
|
|
6606
|
+
const panelRef = useRef(null);
|
|
6607
|
+
const titleId = useId();
|
|
6608
|
+
const pos = usePosition(anchorRef, panelRef, true, { side: "bottom", align: "start", offset: 4, flip: true });
|
|
6609
|
+
const { isTop, returnFocus } = usePopupFocus(true, { trigger: anchorRef, panel: panelRef, close: onClose, tabExits: "edges" });
|
|
6610
|
+
const colours = eventColours(category);
|
|
6611
|
+
const [attendeeScroll, setAttendeeScroll] = useState(null);
|
|
6612
|
+
useKeyboardScroll(attendeeScroll, "Attendees");
|
|
6613
|
+
const closeRef = useLatest(onClose);
|
|
6614
|
+
useEffect(() => {
|
|
6615
|
+
const raf = requestAnimationFrame(() => {
|
|
6616
|
+
const panel = panelRef.current;
|
|
6617
|
+
if (!panel) return;
|
|
6618
|
+
const actions2 = Array.from(panel.querySelectorAll("[data-card-action]"));
|
|
6619
|
+
const safe = actions2.find((el) => el.getAttribute("data-variant") !== "destructive");
|
|
6620
|
+
if (safe) safe.focus();
|
|
6621
|
+
else if (actions2.length) panel.focus();
|
|
6622
|
+
else focusInitial(panel);
|
|
6623
|
+
});
|
|
6624
|
+
return () => cancelAnimationFrame(raf);
|
|
6625
|
+
}, [anchor]);
|
|
6547
6626
|
useEffect(() => {
|
|
6548
|
-
if (!open) return;
|
|
6549
|
-
const raf = requestAnimationFrame(() => focusInitial(floatingRef.current));
|
|
6550
6627
|
const onKey = (e) => {
|
|
6551
6628
|
if (e.key !== "Escape" || e.defaultPrevented || !isTop()) return;
|
|
6552
6629
|
e.preventDefault();
|
|
6553
6630
|
returnFocus();
|
|
6554
|
-
|
|
6631
|
+
closeRef.current();
|
|
6555
6632
|
};
|
|
6556
6633
|
const onDown = (e) => {
|
|
6557
|
-
if (!
|
|
6634
|
+
if (!isTop()) return;
|
|
6635
|
+
const t = e.target;
|
|
6636
|
+
if (!(t instanceof Node) || panelRef.current?.contains(t) || anchor.contains(t)) return;
|
|
6637
|
+
if (t instanceof Element && t.closest(`[${CALENDAR_LAYER}]`)) return;
|
|
6638
|
+
closeRef.current();
|
|
6558
6639
|
};
|
|
6559
6640
|
document.addEventListener("keydown", onKey);
|
|
6560
|
-
document.addEventListener("
|
|
6641
|
+
document.addEventListener("pointerdown", onDown, true);
|
|
6561
6642
|
return () => {
|
|
6562
|
-
cancelAnimationFrame(raf);
|
|
6563
6643
|
document.removeEventListener("keydown", onKey);
|
|
6564
|
-
document.removeEventListener("
|
|
6644
|
+
document.removeEventListener("pointerdown", onDown, true);
|
|
6565
6645
|
};
|
|
6566
|
-
}, [
|
|
6567
|
-
|
|
6646
|
+
}, [anchor, isTop, returnFocus, closeRef]);
|
|
6647
|
+
const run = (action) => {
|
|
6648
|
+
const list = anchor.closest(`[${CALENDAR_LAYER}]`);
|
|
6649
|
+
returnFocus();
|
|
6650
|
+
onClose();
|
|
6651
|
+
action.onClick(event);
|
|
6652
|
+
requestAnimationFrame(() => {
|
|
6653
|
+
const now = document.activeElement;
|
|
6654
|
+
if (now && now !== document.body && now.isConnected) return;
|
|
6655
|
+
if (list?.isConnected && focusInitial(list)) return;
|
|
6656
|
+
fallbackFocus?.()?.focus();
|
|
6657
|
+
});
|
|
6658
|
+
};
|
|
6659
|
+
return createPortal(
|
|
6568
6660
|
/* @__PURE__ */ jsxs(
|
|
6569
|
-
"
|
|
6661
|
+
"div",
|
|
6570
6662
|
{
|
|
6571
|
-
ref:
|
|
6572
|
-
|
|
6573
|
-
"aria-
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6663
|
+
ref: panelRef,
|
|
6664
|
+
role: "dialog",
|
|
6665
|
+
"aria-labelledby": titleId,
|
|
6666
|
+
...{ [CALENDAR_LAYER]: "" },
|
|
6667
|
+
"data-calendar-card": event.id,
|
|
6668
|
+
tabIndex: -1,
|
|
6669
|
+
className: cn(
|
|
6670
|
+
"fixed z-[var(--ds-z-popover)] w-72 max-w-[calc(100vw-2*var(--ds-space-3))] outline-none",
|
|
6671
|
+
"bg-[var(--ds-bg-surface-elevated)]",
|
|
6672
|
+
"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]",
|
|
6673
|
+
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
6674
|
+
"rounded-[var(--ds-radius-md)]",
|
|
6675
|
+
"shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]",
|
|
6676
|
+
"p-ds-3 space-y-ds-2"
|
|
6677
|
+
),
|
|
6678
|
+
style: { top: pos.top, left: pos.left },
|
|
6579
6679
|
children: [
|
|
6580
|
-
"
|
|
6581
|
-
|
|
6582
|
-
|
|
6680
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-ds-2", children: [
|
|
6681
|
+
/* @__PURE__ */ jsx("h3", { id: titleId, className: "font-[var(--ds-weight-heading)] text-sm text-[var(--ds-text-primary)] leading-snug min-w-0 break-words", children: event.title }),
|
|
6682
|
+
/* @__PURE__ */ jsx(
|
|
6683
|
+
Button,
|
|
6684
|
+
{
|
|
6685
|
+
variant: "ghost",
|
|
6686
|
+
size: "icon-sm",
|
|
6687
|
+
"aria-label": "Close",
|
|
6688
|
+
...{ [OVERLAY_CLOSE_ATTR]: "" },
|
|
6689
|
+
onClick: () => {
|
|
6690
|
+
returnFocus();
|
|
6691
|
+
onClose();
|
|
6692
|
+
},
|
|
6693
|
+
className: "-mt-ds-1 -mr-ds-1 shrink-0",
|
|
6694
|
+
children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 14 })
|
|
6695
|
+
}
|
|
6696
|
+
)
|
|
6697
|
+
] }),
|
|
6698
|
+
category && /* @__PURE__ */ jsxs("p", { className: "inline-flex items-center gap-ds-1.5 text-xs text-[var(--ds-text-secondary)]", children: [
|
|
6699
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "inline-block w-2 h-2 rounded-[var(--ds-radius-full)]", style: { backgroundColor: colours.edge } }),
|
|
6700
|
+
category.label
|
|
6701
|
+
] }),
|
|
6702
|
+
/* @__PURE__ */ jsxs("p", { className: "text-xs text-[var(--ds-text-secondary)] tabular-nums", children: [
|
|
6703
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: formatEventWhen(event) }),
|
|
6704
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: formatEventWhen(event, true) })
|
|
6705
|
+
] }),
|
|
6706
|
+
event.location && /* @__PURE__ */ jsxs("p", { className: "text-xs text-[var(--ds-text-secondary)] flex items-start gap-ds-1", children: [
|
|
6707
|
+
/* @__PURE__ */ jsx(Icon, { name: "map-pin", size: 14, className: "shrink-0 mt-px" }),
|
|
6708
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 break-words", children: event.location })
|
|
6709
|
+
] }),
|
|
6710
|
+
event.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-[var(--ds-text-secondary)] whitespace-pre-line break-words", children: event.description }),
|
|
6711
|
+
event.attendees && event.attendees.length > 0 && /* @__PURE__ */ jsx("div", { ref: setAttendeeScroll, className: "max-h-32 overflow-y-auto", children: /* @__PURE__ */ jsx("ul", { "aria-label": "Attendees", className: "space-y-ds-1", children: event.attendees.map((person, i) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-ds-2 text-xs text-[var(--ds-text-primary)]", children: [
|
|
6712
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "shrink-0", children: /* @__PURE__ */ jsx(Avatar, { size: "sm", initials: person.initials ?? person.name }) }),
|
|
6713
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: person.name })
|
|
6714
|
+
] }, `${person.name}-${i}`)) }) }),
|
|
6715
|
+
actions.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-ds-2 pt-ds-1", children: actions.map((action) => /* @__PURE__ */ jsx(Button, { "data-card-action": "", size: "sm", variant: action.variant ?? "secondary", iconLeft: action.iconLeft, onClick: () => run(action), children: action.label }, action.label)) })
|
|
6583
6716
|
]
|
|
6584
6717
|
}
|
|
6585
6718
|
),
|
|
6586
|
-
|
|
6587
|
-
/* @__PURE__ */ jsxs(
|
|
6588
|
-
"div",
|
|
6589
|
-
{
|
|
6590
|
-
ref: floatingRef,
|
|
6591
|
-
role: "dialog",
|
|
6592
|
-
"aria-label": date.toLocaleDateString(formatLocale(), { weekday: "long", month: "long", day: "numeric" }),
|
|
6593
|
-
className: cn(
|
|
6594
|
-
"fixed z-[var(--ds-z-popover)] w-56 max-h-48 overflow-y-auto",
|
|
6595
|
-
"bg-[var(--ds-bg-surface-elevated)]",
|
|
6596
|
-
"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]",
|
|
6597
|
-
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
6598
|
-
"rounded-[var(--ds-radius-md)]",
|
|
6599
|
-
"shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]",
|
|
6600
|
-
"p-ds-2 space-y-ds-1"
|
|
6601
|
-
),
|
|
6602
|
-
style: { top: pos.top, left: pos.left },
|
|
6603
|
-
onClick: (e) => e.stopPropagation(),
|
|
6604
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
6605
|
-
children: [
|
|
6606
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-[var(--ds-text-muted)] px-ds-1 mb-ds-1", children: date.toLocaleDateString(formatLocale(), { weekday: "short", month: "short", day: "numeric" }) }),
|
|
6607
|
-
events.map((event) => /* @__PURE__ */ jsx(
|
|
6608
|
-
EventBar,
|
|
6609
|
-
{
|
|
6610
|
-
event,
|
|
6611
|
-
category: categories[event.category ?? ""],
|
|
6612
|
-
onClick: onEventClick
|
|
6613
|
-
},
|
|
6614
|
-
event.id
|
|
6615
|
-
))
|
|
6616
|
-
]
|
|
6617
|
-
}
|
|
6618
|
-
),
|
|
6619
|
-
document.body
|
|
6620
|
-
)
|
|
6621
|
-
] });
|
|
6622
|
-
}
|
|
6623
|
-
function MonthView({
|
|
6624
|
-
date,
|
|
6625
|
-
events,
|
|
6626
|
-
categories,
|
|
6627
|
-
selectedDate,
|
|
6628
|
-
onDayClick,
|
|
6629
|
-
onEventClick,
|
|
6630
|
-
weekStartsOn
|
|
6631
|
-
}) {
|
|
6632
|
-
const weeks = useMemo(
|
|
6633
|
-
() => getMonthGrid(date.getFullYear(), date.getMonth(), weekStartsOn),
|
|
6634
|
-
[date, weekStartsOn]
|
|
6719
|
+
document.body
|
|
6635
6720
|
);
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6721
|
+
}
|
|
6722
|
+
function DayList({ day, events, categories, anchor, onOpenEvent, onNewEvent, onClose }) {
|
|
6723
|
+
const anchorRef = useMemo(() => ({ current: anchor }), [anchor]);
|
|
6724
|
+
const panelRef = useRef(null);
|
|
6725
|
+
const pos = usePosition(anchorRef, panelRef, true, { side: "bottom", align: "start", offset: 4, flip: true });
|
|
6726
|
+
const { isTop, returnFocus } = usePopupFocus(true, { trigger: anchorRef, panel: panelRef, close: onClose, tabExits: "edges" });
|
|
6727
|
+
const closeRef = useLatest(onClose);
|
|
6728
|
+
useEffect(() => {
|
|
6729
|
+
const raf = requestAnimationFrame(() => focusInitial(panelRef.current));
|
|
6730
|
+
return () => cancelAnimationFrame(raf);
|
|
6731
|
+
}, [anchor]);
|
|
6732
|
+
useEffect(() => {
|
|
6733
|
+
const onKey = (e) => {
|
|
6734
|
+
if (e.key !== "Escape" || e.defaultPrevented || !isTop()) return;
|
|
6735
|
+
e.preventDefault();
|
|
6736
|
+
returnFocus();
|
|
6737
|
+
closeRef.current();
|
|
6738
|
+
};
|
|
6739
|
+
const onDown = (e) => {
|
|
6740
|
+
if (!isTop()) return;
|
|
6741
|
+
const t = e.target;
|
|
6742
|
+
if (!(t instanceof Node) || panelRef.current?.contains(t) || anchor.contains(t)) return;
|
|
6743
|
+
if (t instanceof Element && t.closest(`[${CALENDAR_LAYER}]`)) return;
|
|
6744
|
+
closeRef.current();
|
|
6745
|
+
};
|
|
6746
|
+
document.addEventListener("keydown", onKey);
|
|
6747
|
+
document.addEventListener("pointerdown", onDown, true);
|
|
6748
|
+
return () => {
|
|
6749
|
+
document.removeEventListener("keydown", onKey);
|
|
6750
|
+
document.removeEventListener("pointerdown", onDown, true);
|
|
6751
|
+
};
|
|
6752
|
+
}, [anchor, isTop, returnFocus, closeRef]);
|
|
6753
|
+
return createPortal(
|
|
6754
|
+
/* @__PURE__ */ jsxs(
|
|
6640
6755
|
"div",
|
|
6641
6756
|
{
|
|
6642
|
-
|
|
6757
|
+
ref: panelRef,
|
|
6758
|
+
role: "dialog",
|
|
6759
|
+
"aria-label": formatDayLong(day),
|
|
6760
|
+
...{ [CALENDAR_LAYER]: "" },
|
|
6761
|
+
className: cn(
|
|
6762
|
+
"fixed z-[var(--ds-z-popover)] w-60 max-h-72 overflow-y-auto",
|
|
6763
|
+
"bg-[var(--ds-bg-surface-elevated)]",
|
|
6764
|
+
"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]",
|
|
6765
|
+
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
6766
|
+
"rounded-[var(--ds-radius-md)]",
|
|
6767
|
+
"shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]",
|
|
6768
|
+
"p-ds-2 space-y-ds-1"
|
|
6769
|
+
),
|
|
6770
|
+
style: { top: pos.top, left: pos.left },
|
|
6771
|
+
onClick: (e) => e.stopPropagation(),
|
|
6643
6772
|
children: [
|
|
6644
|
-
/* @__PURE__ */ jsx("
|
|
6645
|
-
/* @__PURE__ */ jsx("
|
|
6773
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-[var(--ds-text-muted)] px-ds-1 mb-ds-1", children: formatDayShort(day) }),
|
|
6774
|
+
events.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-xs text-[var(--ds-text-secondary)] px-ds-1", children: "No events" }),
|
|
6775
|
+
events.map((event) => /* @__PURE__ */ jsx(EventBar, { event, category: categories[event.category ?? ""], onOpen: onOpenEvent }, event.id)),
|
|
6776
|
+
onNewEvent && /* @__PURE__ */ jsx(
|
|
6777
|
+
Button,
|
|
6778
|
+
{
|
|
6779
|
+
variant: "ghost",
|
|
6780
|
+
size: "sm",
|
|
6781
|
+
iconLeft: /* @__PURE__ */ jsx(Icon, { name: "plus", size: 14 }),
|
|
6782
|
+
className: "w-full justify-start mt-ds-1",
|
|
6783
|
+
onClick: () => {
|
|
6784
|
+
returnFocus();
|
|
6785
|
+
onClose();
|
|
6786
|
+
onNewEvent(day);
|
|
6787
|
+
},
|
|
6788
|
+
children: "New event"
|
|
6789
|
+
}
|
|
6790
|
+
)
|
|
6646
6791
|
]
|
|
6647
|
-
}
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6792
|
+
}
|
|
6793
|
+
),
|
|
6794
|
+
document.body
|
|
6795
|
+
);
|
|
6796
|
+
}
|
|
6797
|
+
|
|
6798
|
+
// ../../showcase/src/components/Calendar/styles.ts
|
|
6799
|
+
var TODAY_CIRCLE = "bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] text-[var(--ds-text-on-primary)] font-bold";
|
|
6800
|
+
var LANES = 3;
|
|
6801
|
+
var LANE_H = 20;
|
|
6802
|
+
var LANE_GAP = 4;
|
|
6803
|
+
var NUMBER_ROW = 30;
|
|
6804
|
+
var INSET = "var(--ds-space-1)";
|
|
6805
|
+
function MonthView({ date, events, categories, selectedDate, onDayClick, canStartEvent, onOpenEvent, onNavigate, weekStartsOn }) {
|
|
6806
|
+
const weeks = useMemo(() => getMonthGrid(date.getFullYear(), date.getMonth(), weekStartsOn), [date, weekStartsOn]);
|
|
6807
|
+
const phone = useBreakpoint("sm");
|
|
6808
|
+
const names = { short: weekdayNames(weekStartsOn, "short"), narrow: weekdayNames(weekStartsOn, "narrow"), long: weekdayNames(weekStartsOn, "long") };
|
|
6809
|
+
const layouts = useMemo(() => weeks.map((week) => layoutWeek(events, week, LANES)), [weeks, events]);
|
|
6810
|
+
const currentMonth = date.getMonth();
|
|
6811
|
+
const gridRef = useRef(null);
|
|
6812
|
+
const [list, setList] = useState(null);
|
|
6813
|
+
const inMonth = (d) => !!d && d.getMonth() === currentMonth && d.getFullYear() === date.getFullYear();
|
|
6814
|
+
const fallback = inMonth(selectedDate) ? selectedDate : inMonth(/* @__PURE__ */ new Date()) ? /* @__PURE__ */ new Date() : new Date(date.getFullYear(), currentMonth, 1);
|
|
6815
|
+
const [activeDay, setActiveDay] = useState(fallback);
|
|
6816
|
+
const active = inMonth(activeDay) ? activeDay : fallback;
|
|
6817
|
+
const openList = (day, anchor) => setList({ day, anchor });
|
|
6818
|
+
const choose = (day, anchor) => phone ? openList(day, anchor) : onDayClick(day);
|
|
6819
|
+
const grid = useGridKeyboard({
|
|
6820
|
+
container: gridRef,
|
|
6821
|
+
active,
|
|
6822
|
+
setActive: (d) => {
|
|
6823
|
+
setActiveDay(d);
|
|
6824
|
+
if (!inMonth(d)) onNavigate(d);
|
|
6825
|
+
},
|
|
6826
|
+
keyOf: dayKey,
|
|
6827
|
+
move: (from, e) => moveDay(from, e.key, e.shiftKey, weekStartsOn),
|
|
6828
|
+
onActivate: (day, e) => choose(day, e.currentTarget.querySelector(`[data-grid-key="${dayKey(day)}"]`) ?? e.target)
|
|
6829
|
+
});
|
|
6830
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
|
|
6831
|
+
/* @__PURE__ */ jsxs("div", { ref: gridRef, role: "grid", "aria-label": formatMonthYear(date), onKeyDown: grid.onKeyDown, className: "flex flex-col flex-1 min-h-0", children: [
|
|
6832
|
+
/* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]", children: names.short.map((name, i) => /* @__PURE__ */ jsx("div", { role: "columnheader", "aria-label": names.long[i], className: "text-center text-xs font-medium text-[var(--ds-text-muted)] py-ds-2 px-ds-1", children: phone ? names.narrow[i] : name }, i)) }),
|
|
6833
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col flex-1", children: weeks.map((week, wi) => {
|
|
6834
|
+
const layout = layouts[wi];
|
|
6660
6835
|
const lastRow = wi === weeks.length - 1;
|
|
6661
|
-
return /* @__PURE__ */
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
}
|
|
6704
|
-
)
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6836
|
+
return /* @__PURE__ */ jsx("div", { role: "row", className: "relative grid grid-cols-7 flex-1", children: week.map((day, di) => {
|
|
6837
|
+
const dayEvents = getEventsForDay(events, day);
|
|
6838
|
+
const isCurrentMonth = day.getMonth() === currentMonth;
|
|
6839
|
+
const today = isToday(day);
|
|
6840
|
+
const selected = !!selectedDate && isSameDay(day, selectedDate);
|
|
6841
|
+
const weekend = isWeekend(day);
|
|
6842
|
+
const more = layout.more[di];
|
|
6843
|
+
const label = phone && dayEvents.length > 0 ? `${formatDayLong(day)}, ${dayEvents.length} ${dayEvents.length === 1 ? "event" : "events"}` : formatDayLong(day);
|
|
6844
|
+
return /* @__PURE__ */ jsxs(
|
|
6845
|
+
"div",
|
|
6846
|
+
{
|
|
6847
|
+
role: "gridcell",
|
|
6848
|
+
"data-grid-key": dayKey(day),
|
|
6849
|
+
tabIndex: grid.tabIndexOf(day),
|
|
6850
|
+
"aria-label": label,
|
|
6851
|
+
"aria-selected": selected,
|
|
6852
|
+
"aria-current": today ? "date" : void 0,
|
|
6853
|
+
onFocus: () => {
|
|
6854
|
+
if (!isSameDay(day, active)) setActiveDay(day);
|
|
6855
|
+
},
|
|
6856
|
+
onClick: (e) => choose(day, e.currentTarget),
|
|
6857
|
+
className: cn(
|
|
6858
|
+
"relative min-h-[80px] sm:min-h-[100px] border-[var(--ds-border-subtle)]",
|
|
6859
|
+
!lastRow && "border-b-[length:var(--ds-divider-width)]",
|
|
6860
|
+
di < 6 && "border-r-[length:var(--ds-divider-width)]",
|
|
6861
|
+
"p-ds-1 flex flex-col cursor-pointer transition-colors",
|
|
6862
|
+
FOCUS_INSET,
|
|
6863
|
+
"hover:bg-[var(--ds-bg-muted)]",
|
|
6864
|
+
!isCurrentMonth && "[&>.gs-day-number]:opacity-40",
|
|
6865
|
+
selected && "bg-[var(--ds-accent-whisper)]",
|
|
6866
|
+
weekend && isCurrentMonth && !selected && "bg-[var(--ds-bg-muted)]/30"
|
|
6867
|
+
),
|
|
6868
|
+
children: [
|
|
6869
|
+
/* @__PURE__ */ jsx("span", { className: cn("gs-day-number text-xs w-6 h-6 flex items-center justify-center rounded-[var(--ds-radius-full)] shrink-0", today ? TODAY_CIRCLE : "text-[var(--ds-text-secondary)]"), children: day.getDate() }),
|
|
6870
|
+
phone ? (
|
|
6871
|
+
// dots, a day's presence of events: the day itself is what a tap opens (D46)
|
|
6872
|
+
/* @__PURE__ */ jsxs("span", { "aria-hidden": "true", className: "flex gap-ds-0.5 flex-wrap mt-ds-0.5", children: [
|
|
6873
|
+
dayEvents.slice(0, 4).map((event) => /* @__PURE__ */ jsx("span", { className: "w-1.5 h-1.5 rounded-[var(--ds-radius-full)]", style: { backgroundColor: eventColours(categories[event.category ?? ""]).edge } }, event.id)),
|
|
6874
|
+
dayEvents.length > 4 && /* @__PURE__ */ jsxs("span", { className: "text-2xs text-[var(--ds-text-muted)] leading-none", children: [
|
|
6875
|
+
"+",
|
|
6876
|
+
dayEvents.length - 4
|
|
6877
|
+
] })
|
|
6878
|
+
] })
|
|
6879
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6880
|
+
layout.segments.filter((s) => s.startCol === di).map((s) => /* @__PURE__ */ jsx(
|
|
6881
|
+
EventBar,
|
|
6882
|
+
{
|
|
6883
|
+
event: s.event,
|
|
6884
|
+
category: categories[s.event.category ?? ""],
|
|
6885
|
+
onOpen: onOpenEvent,
|
|
6886
|
+
continuesBefore: s.continuesBefore,
|
|
6887
|
+
continuesAfter: s.continuesAfter,
|
|
6888
|
+
className: "absolute z-[1] flex items-center",
|
|
6889
|
+
style: {
|
|
6890
|
+
top: NUMBER_ROW + s.lane * (LANE_H + LANE_GAP),
|
|
6891
|
+
height: LANE_H,
|
|
6892
|
+
left: s.continuesBefore ? 0 : INSET,
|
|
6893
|
+
width: `calc(${s.span} * (100% + var(--ds-divider-width)) - var(--ds-divider-width) - ${s.continuesBefore ? "0px" : INSET} - ${s.continuesAfter ? "0px" : INSET})`
|
|
6894
|
+
}
|
|
6895
|
+
},
|
|
6896
|
+
`${s.event.id}-${s.startCol}`
|
|
6897
|
+
)),
|
|
6898
|
+
more.length > 0 && /* @__PURE__ */ jsxs(
|
|
6899
|
+
"button",
|
|
6900
|
+
{
|
|
6901
|
+
type: "button",
|
|
6902
|
+
"aria-haspopup": "dialog",
|
|
6903
|
+
"aria-expanded": !!list && isSameDay(list.day, day),
|
|
6904
|
+
className: "absolute z-[1] text-2xs text-[var(--ds-accent-text,var(--ds-accent-primary))] font-medium cursor-pointer hover:underline px-ds-1.5 rounded-[var(--ds-radius-sm)] focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
6905
|
+
style: { top: NUMBER_ROW + (LANES - 1) * (LANE_H + LANE_GAP), left: INSET, height: LANE_H },
|
|
6906
|
+
onClick: (e) => {
|
|
6907
|
+
e.stopPropagation();
|
|
6908
|
+
openList(day, e.currentTarget);
|
|
6909
|
+
},
|
|
6910
|
+
children: [
|
|
6911
|
+
"+",
|
|
6912
|
+
more.length,
|
|
6913
|
+
" more"
|
|
6914
|
+
]
|
|
6915
|
+
}
|
|
6916
|
+
)
|
|
6720
6917
|
] })
|
|
6721
|
-
]
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
);
|
|
6726
|
-
})
|
|
6727
|
-
|
|
6918
|
+
]
|
|
6919
|
+
},
|
|
6920
|
+
dayKey(day)
|
|
6921
|
+
);
|
|
6922
|
+
}) }, dayKey(week[0]));
|
|
6923
|
+
}) })
|
|
6924
|
+
] }),
|
|
6925
|
+
list && /* @__PURE__ */ jsx(
|
|
6926
|
+
DayList,
|
|
6927
|
+
{
|
|
6928
|
+
day: list.day,
|
|
6929
|
+
events: getEventsForDay(events, list.day),
|
|
6930
|
+
categories,
|
|
6931
|
+
anchor: list.anchor,
|
|
6932
|
+
onOpenEvent,
|
|
6933
|
+
onNewEvent: phone && canStartEvent ? onDayClick : void 0,
|
|
6934
|
+
onClose: () => setList(null)
|
|
6935
|
+
}
|
|
6936
|
+
)
|
|
6728
6937
|
] });
|
|
6729
6938
|
}
|
|
6730
6939
|
var HOUR_HEIGHT = 40;
|
|
6731
6940
|
var HOURS = Array.from({ length: 24 }, (_, i) => i);
|
|
6732
6941
|
var GRID_HEIGHT = HOURS.length * HOUR_HEIGHT;
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
|
|
6942
|
+
var MIN_EVENT_PX = 24;
|
|
6943
|
+
var MIN_EVENT_MINUTES = MIN_EVENT_PX / HOUR_HEIGHT * 60;
|
|
6944
|
+
var ALL_DAY_LANES = 3;
|
|
6945
|
+
var LANE_H2 = 20;
|
|
6946
|
+
var LANE_GAP2 = 4;
|
|
6947
|
+
var WORKING_DAY = 8;
|
|
6948
|
+
var HOUR_LABEL_ROOM = 8;
|
|
6949
|
+
var FADE = 24;
|
|
6950
|
+
var MIN_DAY_WIDTH = 100;
|
|
6951
|
+
var hh = (hour) => String(hour).padStart(2, "0");
|
|
6952
|
+
var cellKey = (day, hour) => hour === null ? dayKey(day) : `${dayKey(day)}T${hh(hour)}`;
|
|
6953
|
+
function parseKey(key) {
|
|
6954
|
+
const [d, h] = key.split("T");
|
|
6955
|
+
const [y, m, dd] = d.split("-").map(Number);
|
|
6956
|
+
return { day: new Date(y, m - 1, dd), hour: h === void 0 ? null : Number(h) };
|
|
6957
|
+
}
|
|
6958
|
+
function NowLine() {
|
|
6959
|
+
const [now, setNow] = useState(() => /* @__PURE__ */ new Date());
|
|
6741
6960
|
useEffect(() => {
|
|
6742
6961
|
const id = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
|
|
6743
6962
|
return () => clearInterval(id);
|
|
6744
6963
|
}, []);
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
function TimedEvent({
|
|
6759
|
-
event,
|
|
6760
|
-
category,
|
|
6761
|
-
column,
|
|
6762
|
-
totalColumns,
|
|
6763
|
-
onEventClick
|
|
6764
|
-
}) {
|
|
6765
|
-
const start = new Date(event.start);
|
|
6766
|
-
const end = event.end ? new Date(event.end) : new Date(start.getTime() + 60 * 6e4);
|
|
6767
|
-
const top = timeToFraction(start) * GRID_HEIGHT;
|
|
6768
|
-
const bottom = timeToFraction(end) * GRID_HEIGHT;
|
|
6769
|
-
const height = Math.max(bottom - top, 20);
|
|
6770
|
-
const color = category?.color ?? "var(--ds-accent-primary)";
|
|
6771
|
-
const width = `calc(${100 / totalColumns}% - 2px)`;
|
|
6772
|
-
const left = `calc(${column / totalColumns * 100}% + 1px)`;
|
|
6964
|
+
return /* @__PURE__ */ jsx("div", { "data-now-line": "", "aria-hidden": "true", className: "absolute left-0 right-0 z-[2] pointer-events-none", style: { top: timeToFraction(now) * GRID_HEIGHT }, children: /* @__PURE__ */ jsx("div", { className: "relative border-t-2 border-[var(--ds-accent-primary)]", children: /* @__PURE__ */ jsx("span", { className: "absolute -left-1 -top-[5px] box-border w-2 h-2 rounded-[var(--ds-radius-full)] border-4 border-[var(--ds-accent-primary)]" }) }) });
|
|
6965
|
+
}
|
|
6966
|
+
function TimedEvent({ placed, category, onOpen, onFocusEvent }) {
|
|
6967
|
+
const { piece, column, columns } = placed;
|
|
6968
|
+
const { event } = piece;
|
|
6969
|
+
const top = timeToFraction(piece.start) * GRID_HEIGHT;
|
|
6970
|
+
const bottom = piece.end.getHours() === 0 && piece.end.getMinutes() === 0 && piece.end > piece.start ? GRID_HEIGHT : timeToFraction(piece.end) * GRID_HEIGHT;
|
|
6971
|
+
const height = Math.max(bottom - top, MIN_EVENT_PX);
|
|
6972
|
+
const drawnTop = Math.min(top, GRID_HEIGHT - height);
|
|
6973
|
+
const colours = eventColours(category);
|
|
6974
|
+
const end = event.end && event.end > event.start ? event.end : void 0;
|
|
6975
|
+
const cutTop = piece.start > event.start;
|
|
6976
|
+
const cutBottom = !!end && piece.end < end;
|
|
6773
6977
|
return /* @__PURE__ */ jsxs(
|
|
6774
|
-
"
|
|
6978
|
+
"button",
|
|
6775
6979
|
{
|
|
6980
|
+
type: "button",
|
|
6981
|
+
"data-calendar-event": event.id,
|
|
6982
|
+
"aria-label": eventName(event, category),
|
|
6776
6983
|
className: cn(
|
|
6777
|
-
|
|
6778
|
-
"
|
|
6779
|
-
"
|
|
6780
|
-
"
|
|
6984
|
+
// a short event keeps its title whole: no padding above and below it
|
|
6985
|
+
"absolute pointer-events-auto text-left px-ds-1.5 text-xs leading-tight",
|
|
6986
|
+
height > 30 ? "py-ds-1" : "py-0 justify-center",
|
|
6987
|
+
"flex flex-col items-start overflow-hidden cursor-pointer transition-[filter] hover:brightness-95",
|
|
6988
|
+
height > 30 && "justify-start",
|
|
6989
|
+
"border-[length:var(--ds-border-width)] border-solid rounded-[var(--ds-radius-sm)]",
|
|
6990
|
+
cutTop && "rounded-t-none border-t-0",
|
|
6991
|
+
cutBottom && "rounded-b-none border-b-0",
|
|
6992
|
+
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)] focus-visible:z-[3]"
|
|
6781
6993
|
),
|
|
6782
6994
|
style: {
|
|
6783
|
-
top,
|
|
6995
|
+
top: drawnTop,
|
|
6784
6996
|
height,
|
|
6785
|
-
left
|
|
6786
|
-
width
|
|
6787
|
-
backgroundColor:
|
|
6788
|
-
color,
|
|
6789
|
-
|
|
6997
|
+
left: `calc(${column / columns * 100}% + 1px)`,
|
|
6998
|
+
width: `calc(${100 / columns}% - 2px)`,
|
|
6999
|
+
backgroundColor: colours.fill,
|
|
7000
|
+
color: colours.text,
|
|
7001
|
+
borderColor: colours.edge
|
|
6790
7002
|
},
|
|
6791
7003
|
onClick: (e) => {
|
|
6792
7004
|
e.stopPropagation();
|
|
6793
|
-
|
|
7005
|
+
onOpen(event, e.currentTarget);
|
|
6794
7006
|
},
|
|
6795
|
-
|
|
6796
|
-
role: "button",
|
|
6797
|
-
tabIndex: 0,
|
|
7007
|
+
onFocus: onFocusEvent,
|
|
6798
7008
|
children: [
|
|
6799
|
-
/* @__PURE__ */ jsx("
|
|
6800
|
-
height > 30 && /* @__PURE__ */
|
|
6801
|
-
formatTime(start),
|
|
6802
|
-
" \u2013 ",
|
|
6803
|
-
formatTime(end)
|
|
6804
|
-
] })
|
|
7009
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium truncate w-full", children: event.title }),
|
|
7010
|
+
height > 30 && /* @__PURE__ */ jsx("span", { className: "text-2xs truncate w-full tabular-nums", children: formatTimeRange(event.start, end) })
|
|
6805
7011
|
]
|
|
6806
7012
|
}
|
|
6807
7013
|
);
|
|
6808
7014
|
}
|
|
6809
|
-
function WeekView({
|
|
6810
|
-
date,
|
|
6811
|
-
events,
|
|
6812
|
-
categories,
|
|
6813
|
-
selectedDate,
|
|
6814
|
-
onDayClick,
|
|
6815
|
-
onEventClick,
|
|
6816
|
-
weekStartsOn
|
|
6817
|
-
}) {
|
|
7015
|
+
function WeekView({ date, events, categories, selectedDate, onDayClick, onOpenEvent, onNavigate, weekStartsOn }) {
|
|
6818
7016
|
const days = useMemo(() => getWeekDays(date, weekStartsOn), [date, weekStartsOn]);
|
|
6819
|
-
const
|
|
6820
|
-
|
|
6821
|
-
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
const
|
|
6825
|
-
const
|
|
7017
|
+
const names = weekdayNames(weekStartsOn, "short");
|
|
7018
|
+
const barEvents = useMemo(() => events.filter(isBarEvent), [events]);
|
|
7019
|
+
const allDay = useMemo(() => layoutWeek(barEvents, days, ALL_DAY_LANES), [barEvents, days]);
|
|
7020
|
+
const pieces = useMemo(() => days.map((day) => layoutPieces(dayPieces(events, day), MIN_EVENT_MINUTES)), [days, events]);
|
|
7021
|
+
const allDayHeight = Math.max(28, 4 + allDay.lanes * (LANE_H2 + LANE_GAP2) + 2);
|
|
7022
|
+
const rootRef = useRef(null);
|
|
7023
|
+
const scrollerRef = useRef(null);
|
|
6826
7024
|
const syncingScroll = useRef(false);
|
|
6827
7025
|
const { ref: edgesRef, measure: measureEdges, fadeProps: edgeFade } = useScrollEdges();
|
|
7026
|
+
const [list, setList] = useState(null);
|
|
6828
7027
|
const handleScroll = useCallback((e) => {
|
|
6829
7028
|
if (syncingScroll.current) return;
|
|
6830
7029
|
syncingScroll.current = true;
|
|
6831
7030
|
const source = e.target;
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
panels?.forEach((panel) => {
|
|
6835
|
-
if (panel !== source) panel.scrollLeft = scrollLeft;
|
|
7031
|
+
rootRef.current?.querySelectorAll("[data-week-scroll]").forEach((panel) => {
|
|
7032
|
+
if (panel !== source) panel.scrollLeft = source.scrollLeft;
|
|
6836
7033
|
});
|
|
6837
7034
|
syncingScroll.current = false;
|
|
6838
7035
|
}, []);
|
|
6839
7036
|
useEffect(() => {
|
|
6840
|
-
const
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
7037
|
+
const panels = rootRef.current?.querySelectorAll("[data-week-scroll]");
|
|
7038
|
+
panels?.forEach((panel) => panel.addEventListener("scroll", handleScroll));
|
|
7039
|
+
return () => panels?.forEach((panel) => panel.removeEventListener("scroll", handleScroll));
|
|
7040
|
+
}, [handleScroll]);
|
|
7041
|
+
const starts = pieces.flat().filter((p) => p.piece.start.getTime() === p.piece.event.start.getTime()).map((p) => p.piece.start.getHours() + p.piece.start.getMinutes() / 60);
|
|
7042
|
+
const earliest = Math.floor(Math.min(WORKING_DAY, ...starts));
|
|
7043
|
+
const topOf = (hour) => Math.max(0, hour * HOUR_HEIGHT - HOUR_LABEL_ROOM);
|
|
7044
|
+
const openingHourRef = useLatest(earliest);
|
|
7045
|
+
const opened = useRef(null);
|
|
7046
|
+
const week = dayKey(days[0]);
|
|
7047
|
+
const weekRef = useLatest(week);
|
|
7048
|
+
const [openingHour] = useState(earliest);
|
|
7049
|
+
useLayoutEffect(() => {
|
|
7050
|
+
const scroller = scrollerRef.current;
|
|
7051
|
+
if (!scroller) return;
|
|
7052
|
+
let done = false;
|
|
7053
|
+
const open = () => {
|
|
7054
|
+
if (done || scroller.scrollHeight <= scroller.clientHeight + 1) return;
|
|
7055
|
+
done = true;
|
|
7056
|
+
scroller.scrollTo({ top: topOf(openingHourRef.current) });
|
|
7057
|
+
opened.current = { top: scroller.scrollTop, week: weekRef.current };
|
|
6846
7058
|
};
|
|
6847
|
-
|
|
6848
|
-
|
|
7059
|
+
open();
|
|
7060
|
+
if (done || typeof ResizeObserver === "undefined") return;
|
|
7061
|
+
const ro = new ResizeObserver(() => {
|
|
7062
|
+
open();
|
|
7063
|
+
if (done) ro.disconnect();
|
|
7064
|
+
});
|
|
7065
|
+
ro.observe(scroller);
|
|
7066
|
+
return () => ro.disconnect();
|
|
7067
|
+
}, [openingHour, openingHourRef, weekRef]);
|
|
7068
|
+
useLayoutEffect(() => {
|
|
7069
|
+
const scroller = scrollerRef.current;
|
|
7070
|
+
const o = opened.current;
|
|
7071
|
+
if (!scroller || !o || o.week !== week) return;
|
|
7072
|
+
if (Math.abs(scroller.scrollTop - o.top) > 1) {
|
|
7073
|
+
opened.current = null;
|
|
7074
|
+
return;
|
|
7075
|
+
}
|
|
7076
|
+
if (topOf(earliest) >= o.top) return;
|
|
7077
|
+
scroller.scrollTo({ top: topOf(earliest) });
|
|
7078
|
+
opened.current = { top: scroller.scrollTop, week };
|
|
7079
|
+
}, [earliest, week]);
|
|
7080
|
+
const inWeek = (d) => days.some((day) => isSameDay(day, d));
|
|
7081
|
+
const anchorDay = selectedDate && inWeek(selectedDate) ? selectedDate : days.find(isToday) ?? days[0];
|
|
7082
|
+
const [activeKey, setActiveKey] = useState(() => cellKey(anchorDay, openingHour));
|
|
7083
|
+
const active = inWeek(parseKey(activeKey).day) ? activeKey : cellKey(anchorDay, parseKey(activeKey).hour);
|
|
7084
|
+
const firstVisibleHour = () => Math.min(23, Math.ceil((scrollerRef.current?.scrollTop ?? 0) / HOUR_HEIGHT));
|
|
7085
|
+
const placeInView = (_key, el) => {
|
|
7086
|
+
const scroller = scrollerRef.current;
|
|
7087
|
+
if (scroller && scroller.contains(el) && scroller.scrollHeight > scroller.clientHeight + 1) {
|
|
7088
|
+
const top = el.offsetTop;
|
|
7089
|
+
if (top < scroller.scrollTop) scroller.scrollTop = top;
|
|
7090
|
+
else if (top + el.offsetHeight > scroller.scrollTop + scroller.clientHeight) scroller.scrollTop = top + el.offsetHeight - scroller.clientHeight;
|
|
7091
|
+
} else {
|
|
7092
|
+
el.scrollIntoView?.({ block: "nearest", inline: "nearest" });
|
|
7093
|
+
}
|
|
7094
|
+
const strip = el.closest("[data-week-scroll]");
|
|
7095
|
+
if (strip) {
|
|
7096
|
+
const cell = el.getBoundingClientRect();
|
|
7097
|
+
const box = strip.getBoundingClientRect();
|
|
7098
|
+
if (cell.left - FADE < box.left) strip.scrollLeft -= box.left - (cell.left - FADE);
|
|
7099
|
+
else if (cell.right + FADE > box.right) strip.scrollLeft += cell.right + FADE - box.right;
|
|
7100
|
+
}
|
|
7101
|
+
};
|
|
7102
|
+
const grid = useGridKeyboard({
|
|
7103
|
+
container: rootRef,
|
|
7104
|
+
active,
|
|
7105
|
+
setActive: (key) => {
|
|
7106
|
+
setActiveKey(key);
|
|
7107
|
+
const { day } = parseKey(key);
|
|
7108
|
+
if (!inWeek(day)) onNavigate(day);
|
|
7109
|
+
},
|
|
7110
|
+
keyOf: (key) => key,
|
|
7111
|
+
move: (from, e) => {
|
|
7112
|
+
const { day, hour } = parseKey(from);
|
|
7113
|
+
const col = days.findIndex((d) => isSameDay(d, day));
|
|
7114
|
+
switch (e.key) {
|
|
7115
|
+
case "ArrowUp":
|
|
7116
|
+
return hour === null ? from : hour === 0 ? cellKey(day, null) : cellKey(day, hour - 1);
|
|
7117
|
+
case "ArrowDown":
|
|
7118
|
+
return hour === null ? cellKey(day, firstVisibleHour()) : cellKey(day, Math.min(23, hour + 1));
|
|
7119
|
+
case "ArrowLeft":
|
|
7120
|
+
return col > 0 ? cellKey(days[col - 1], hour) : from;
|
|
7121
|
+
case "ArrowRight":
|
|
7122
|
+
return col >= 0 && col < days.length - 1 ? cellKey(days[col + 1], hour) : from;
|
|
7123
|
+
case "Home":
|
|
7124
|
+
return cellKey(days[0], hour);
|
|
7125
|
+
case "End":
|
|
7126
|
+
return cellKey(days[days.length - 1], hour);
|
|
7127
|
+
case "PageUp":
|
|
7128
|
+
return cellKey(addDays2(day, -7), hour);
|
|
7129
|
+
case "PageDown":
|
|
7130
|
+
return cellKey(addDays2(day, 7), hour);
|
|
7131
|
+
default:
|
|
7132
|
+
return null;
|
|
7133
|
+
}
|
|
7134
|
+
},
|
|
7135
|
+
onActivate: (key) => {
|
|
7136
|
+
const { day, hour } = parseKey(key);
|
|
7137
|
+
onDayClick(day, hour === null ? void 0 : { time: `${hh(hour)}:00` });
|
|
7138
|
+
},
|
|
7139
|
+
scrollIntoView: placeInView
|
|
7140
|
+
});
|
|
6849
7141
|
const dayGridColumns = `repeat(${days.length}, minmax(${MIN_DAY_WIDTH}px, 1fr))`;
|
|
6850
|
-
|
|
7142
|
+
const stripWidth = MIN_DAY_WIDTH * days.length;
|
|
7143
|
+
const chooseHour = (day, hour) => (e) => {
|
|
7144
|
+
const minutes = e.nativeEvent.offsetY >= HOUR_HEIGHT / 2 ? 30 : 0;
|
|
7145
|
+
onDayClick(day, { time: `${hh(hour)}:${minutes === 30 ? "30" : "00"}` });
|
|
7146
|
+
};
|
|
7147
|
+
return /* @__PURE__ */ jsxs("div", { ref: rootRef, className: "flex flex-col h-full overflow-hidden", onKeyDown: grid.onKeyDown, children: [
|
|
6851
7148
|
/* @__PURE__ */ jsxs("div", { className: "flex border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]", children: [
|
|
6852
7149
|
/* @__PURE__ */ jsx("div", { className: "w-14 shrink-0 border-r-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]" }),
|
|
6853
|
-
/* @__PURE__ */ jsx("div", { ref: edgesRef, onScroll: measureEdges, ...edgeFade, className: "flex-1 overflow-x-auto gs-scrollbar-none", "data-week-scroll": true, children: /* @__PURE__ */ jsx(
|
|
6854
|
-
"div",
|
|
6855
|
-
{
|
|
6856
|
-
|
|
6857
|
-
style: { gridTemplateColumns: dayGridColumns, minWidth: MIN_DAY_WIDTH * days.length },
|
|
6858
|
-
children: days.map((day, i) => {
|
|
6859
|
-
const today = isToday(day);
|
|
6860
|
-
const selected = selectedDate && isSameDay2(day, selectedDate);
|
|
6861
|
-
return /* @__PURE__ */ jsxs(
|
|
6862
|
-
"div",
|
|
6863
|
-
{
|
|
6864
|
-
className: cn(
|
|
6865
|
-
"text-center py-ds-2 cursor-pointer transition-colors",
|
|
6866
|
-
"hover:bg-[var(--ds-bg-muted)]",
|
|
6867
|
-
i > 0 && "border-l-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]",
|
|
6868
|
-
selected && "bg-[var(--ds-accent-whisper)]"
|
|
6869
|
-
),
|
|
6870
|
-
onClick: () => onDayClick?.(day),
|
|
6871
|
-
children: [
|
|
6872
|
-
/* @__PURE__ */ jsx("div", { className: "text-xs text-[var(--ds-text-muted)] font-medium", children: day.toLocaleDateString(formatLocale(), { weekday: "short" }) }),
|
|
6873
|
-
/* @__PURE__ */ jsx(
|
|
6874
|
-
"div",
|
|
6875
|
-
{
|
|
6876
|
-
className: cn(
|
|
6877
|
-
"text-lg font-semibold mt-ds-0.5 mx-auto w-8 h-8 flex items-center justify-center rounded-[var(--ds-radius-full)]",
|
|
6878
|
-
today ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]" : "text-[var(--ds-text-primary)]"
|
|
6879
|
-
),
|
|
6880
|
-
children: day.getDate()
|
|
6881
|
-
}
|
|
6882
|
-
)
|
|
6883
|
-
]
|
|
6884
|
-
},
|
|
6885
|
-
i
|
|
6886
|
-
);
|
|
6887
|
-
})
|
|
6888
|
-
}
|
|
6889
|
-
) })
|
|
7150
|
+
/* @__PURE__ */ jsx("div", { ref: edgesRef, onScroll: measureEdges, ...edgeFade, className: "flex-1 overflow-x-auto gs-scrollbar-none", "data-week-scroll": true, children: /* @__PURE__ */ jsx("div", { className: "grid", style: { gridTemplateColumns: dayGridColumns, minWidth: stripWidth }, children: days.map((day, i) => /* @__PURE__ */ jsxs("div", { className: cn("text-center py-ds-2", i > 0 && "border-l-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]", selectedDate && isSameDay(day, selectedDate) && "bg-[var(--ds-accent-whisper)]"), children: [
|
|
7151
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs text-[var(--ds-text-muted)] font-medium", children: names[i] }),
|
|
7152
|
+
/* @__PURE__ */ jsx("div", { className: cn("text-lg font-semibold mt-ds-0.5 mx-auto w-8 h-8 flex items-center justify-center rounded-[var(--ds-radius-full)]", isToday(day) ? TODAY_CIRCLE : "text-[var(--ds-text-primary)]"), children: day.getDate() })
|
|
7153
|
+
] }, i)) }) })
|
|
6890
7154
|
] }),
|
|
6891
|
-
|
|
7155
|
+
/* @__PURE__ */ jsxs("div", { className: "flex border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] bg-[var(--ds-bg-muted)]/30", children: [
|
|
6892
7156
|
/* @__PURE__ */ jsx("div", { className: "w-14 shrink-0 border-r-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] text-2xs text-[var(--ds-text-muted)] px-ds-1 py-ds-1 text-right", children: "all-day" }),
|
|
6893
|
-
/* @__PURE__ */ jsx("div", { ...edgeFade, className: "flex-1 overflow-x-auto gs-scrollbar-none", "data-week-scroll": true, children: /* @__PURE__ */ jsx(
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
"
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
)
|
|
6905
|
-
|
|
7157
|
+
/* @__PURE__ */ jsx("div", { ...edgeFade, className: "flex-1 overflow-x-auto gs-scrollbar-none", "data-week-scroll": true, children: /* @__PURE__ */ jsx("div", { role: "grid", "aria-label": "All day", "aria-readonly": "true", style: { minWidth: stripWidth }, children: /* @__PURE__ */ jsx("div", { role: "row", className: "grid", style: { gridTemplateColumns: dayGridColumns, height: allDayHeight }, children: days.map((day, i) => {
|
|
7158
|
+
const key = cellKey(day, null);
|
|
7159
|
+
const more = allDay.more[i];
|
|
7160
|
+
return /* @__PURE__ */ jsxs(
|
|
7161
|
+
"div",
|
|
7162
|
+
{
|
|
7163
|
+
role: "gridcell",
|
|
7164
|
+
"data-grid-key": key,
|
|
7165
|
+
tabIndex: grid.tabIndexOf(key),
|
|
7166
|
+
"aria-label": `${formatDayLong(day)}, all day`,
|
|
7167
|
+
onFocus: () => {
|
|
7168
|
+
if (active !== key) setActiveKey(key);
|
|
7169
|
+
},
|
|
7170
|
+
onClick: () => onDayClick(day),
|
|
7171
|
+
className: cn("relative cursor-pointer", FOCUS_INSET, i > 0 && "border-l-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]"),
|
|
7172
|
+
children: [
|
|
7173
|
+
allDay.segments.filter((s) => s.startCol === i).map((s) => /* @__PURE__ */ jsx(
|
|
6906
7174
|
EventBar,
|
|
6907
7175
|
{
|
|
6908
|
-
event,
|
|
6909
|
-
category: categories[event.category ?? ""],
|
|
6910
|
-
|
|
7176
|
+
event: s.event,
|
|
7177
|
+
category: categories[s.event.category ?? ""],
|
|
7178
|
+
onOpen: onOpenEvent,
|
|
7179
|
+
continuesBefore: s.continuesBefore,
|
|
7180
|
+
continuesAfter: s.continuesAfter,
|
|
7181
|
+
className: "absolute z-[1] flex items-center",
|
|
7182
|
+
style: {
|
|
7183
|
+
top: 2 + s.lane * (LANE_H2 + LANE_GAP2),
|
|
7184
|
+
height: LANE_H2,
|
|
7185
|
+
left: s.continuesBefore ? 0 : 2,
|
|
7186
|
+
width: `calc(${s.span} * (100% + var(--ds-divider-width)) - var(--ds-divider-width) - ${s.continuesBefore ? 0 : 2}px - ${s.continuesAfter ? 0 : 2}px)`
|
|
7187
|
+
}
|
|
6911
7188
|
},
|
|
6912
|
-
event.id
|
|
6913
|
-
))
|
|
7189
|
+
`${s.event.id}-${s.startCol}`
|
|
7190
|
+
)),
|
|
7191
|
+
more.length > 0 && /* @__PURE__ */ jsxs(
|
|
7192
|
+
"button",
|
|
7193
|
+
{
|
|
7194
|
+
type: "button",
|
|
7195
|
+
"aria-haspopup": "dialog",
|
|
7196
|
+
"aria-expanded": !!list && isSameDay(list.day, day),
|
|
7197
|
+
className: "absolute z-[1] text-2xs text-[var(--ds-accent-text,var(--ds-accent-primary))] font-medium cursor-pointer hover:underline px-ds-1.5 rounded-[var(--ds-radius-sm)] focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
7198
|
+
style: { top: 2 + (ALL_DAY_LANES - 1) * (LANE_H2 + LANE_GAP2), left: 2, height: LANE_H2 },
|
|
7199
|
+
onClick: (e) => {
|
|
7200
|
+
e.stopPropagation();
|
|
7201
|
+
setList({ day, anchor: e.currentTarget });
|
|
7202
|
+
},
|
|
7203
|
+
children: [
|
|
7204
|
+
"+",
|
|
7205
|
+
more.length,
|
|
7206
|
+
" more"
|
|
7207
|
+
]
|
|
7208
|
+
}
|
|
7209
|
+
)
|
|
7210
|
+
]
|
|
7211
|
+
},
|
|
7212
|
+
i
|
|
7213
|
+
);
|
|
7214
|
+
}) }) }) })
|
|
7215
|
+
] }),
|
|
7216
|
+
/* @__PURE__ */ jsxs("div", { ref: scrollerRef, className: "flex flex-1 min-h-0 overflow-y-auto", "data-week-hours": "", children: [
|
|
7217
|
+
/* @__PURE__ */ jsx("div", { className: "w-14 shrink-0 relative border-r-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]", style: { height: GRID_HEIGHT }, "aria-hidden": "true", children: HOURS.map((h) => /* @__PURE__ */ jsx("div", { className: "absolute right-0 pr-ds-2 text-2xs text-[var(--ds-text-muted)] -translate-y-1/2 tabular-nums", style: { top: h * HOUR_HEIGHT }, children: h > 0 && formatHourLabel(h) }, h)) }),
|
|
7218
|
+
/* @__PURE__ */ jsx("div", { ...edgeFade, className: "flex-1 self-start overflow-x-auto overflow-y-hidden gs-scrollbar-none", style: { height: GRID_HEIGHT }, "data-week-scroll": true, children: /* @__PURE__ */ jsxs("div", { className: "relative", style: { height: GRID_HEIGHT, minWidth: stripWidth }, children: [
|
|
7219
|
+
/* @__PURE__ */ jsx("div", { role: "grid", "aria-label": formatWeekRange(date, weekStartsOn), "aria-readonly": "true", className: "absolute inset-0", children: HOURS.map((hour) => /* @__PURE__ */ jsx("div", { role: "row", className: "grid", style: { gridTemplateColumns: dayGridColumns, height: HOUR_HEIGHT }, children: days.map((day, i) => {
|
|
7220
|
+
const key = cellKey(day, hour);
|
|
7221
|
+
return /* @__PURE__ */ jsx(
|
|
7222
|
+
"div",
|
|
7223
|
+
{
|
|
7224
|
+
role: "gridcell",
|
|
7225
|
+
"data-grid-key": key,
|
|
7226
|
+
tabIndex: grid.tabIndexOf(key),
|
|
7227
|
+
"aria-label": `${formatDayLong(day)}, ${formatTime(new Date(day.getFullYear(), day.getMonth(), day.getDate(), hour))}`,
|
|
7228
|
+
onFocus: () => {
|
|
7229
|
+
if (active !== key) setActiveKey(key);
|
|
7230
|
+
},
|
|
7231
|
+
onClick: chooseHour(day, hour),
|
|
7232
|
+
className: cn(
|
|
7233
|
+
"cursor-pointer border-t-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] hover:bg-[var(--ds-bg-muted)]/40",
|
|
7234
|
+
FOCUS_INSET,
|
|
7235
|
+
i > 0 && "border-l-[length:var(--ds-divider-width)]"
|
|
7236
|
+
)
|
|
6914
7237
|
},
|
|
6915
7238
|
i
|
|
7239
|
+
);
|
|
7240
|
+
}) }, hour)) }),
|
|
7241
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 grid pointer-events-none", style: { gridTemplateColumns: dayGridColumns }, children: days.map((day, i) => /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
7242
|
+
isToday(day) && /* @__PURE__ */ jsx(NowLine, {}),
|
|
7243
|
+
pieces[i].map((placed) => /* @__PURE__ */ jsx(
|
|
7244
|
+
TimedEvent,
|
|
7245
|
+
{
|
|
7246
|
+
placed,
|
|
7247
|
+
category: categories[placed.piece.event.category ?? ""],
|
|
7248
|
+
onOpen: onOpenEvent,
|
|
7249
|
+
onFocusEvent: () => setActiveKey(cellKey(day, placed.piece.start.getHours()))
|
|
7250
|
+
},
|
|
7251
|
+
`${placed.piece.event.id}-${i}`
|
|
6916
7252
|
))
|
|
6917
|
-
}
|
|
6918
|
-
) })
|
|
7253
|
+
] }, i)) })
|
|
7254
|
+
] }) })
|
|
6919
7255
|
] }),
|
|
6920
|
-
/* @__PURE__ */
|
|
6921
|
-
/* @__PURE__ */ jsx("div", { className: "w-14 shrink-0 relative border-r-[length:var(--ds-divider-width)] border-t-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]", style: { height: GRID_HEIGHT }, children: HOURS.map((h) => /* @__PURE__ */ jsx(
|
|
6922
|
-
"div",
|
|
6923
|
-
{
|
|
6924
|
-
className: "absolute right-0 pr-ds-2 text-2xs text-[var(--ds-text-muted)] -translate-y-1/2",
|
|
6925
|
-
style: { top: h * HOUR_HEIGHT },
|
|
6926
|
-
children: h > 0 && formatHour(h)
|
|
6927
|
-
},
|
|
6928
|
-
h
|
|
6929
|
-
)) }),
|
|
6930
|
-
/* @__PURE__ */ jsx("div", { ...edgeFade, className: "flex-1 overflow-x-auto gs-scrollbar-none", "data-week-scroll": true, children: /* @__PURE__ */ jsx(
|
|
6931
|
-
"div",
|
|
6932
|
-
{
|
|
6933
|
-
className: "relative",
|
|
6934
|
-
style: { height: GRID_HEIGHT, minWidth: MIN_DAY_WIDTH * days.length },
|
|
6935
|
-
children: /* @__PURE__ */ jsx(
|
|
6936
|
-
"div",
|
|
6937
|
-
{
|
|
6938
|
-
className: "grid h-full",
|
|
6939
|
-
style: { gridTemplateColumns: dayGridColumns },
|
|
6940
|
-
children: days.map((day, i) => {
|
|
6941
|
-
const dayEvents = getEventsForDay(events, day).filter((e) => !e.allDay);
|
|
6942
|
-
const layout = getOverlappingGroups(dayEvents);
|
|
6943
|
-
const today = isToday(day);
|
|
6944
|
-
return /* @__PURE__ */ jsxs(
|
|
6945
|
-
"div",
|
|
6946
|
-
{
|
|
6947
|
-
className: cn(
|
|
6948
|
-
"relative",
|
|
6949
|
-
i > 0 && "border-l-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]"
|
|
6950
|
-
),
|
|
6951
|
-
onClick: () => onDayClick?.(day),
|
|
6952
|
-
children: [
|
|
6953
|
-
HOURS.map((h) => /* @__PURE__ */ jsx(
|
|
6954
|
-
"div",
|
|
6955
|
-
{
|
|
6956
|
-
className: "absolute left-0 right-0 border-t-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]",
|
|
6957
|
-
style: { top: h * HOUR_HEIGHT }
|
|
6958
|
-
},
|
|
6959
|
-
h
|
|
6960
|
-
)),
|
|
6961
|
-
today && /* @__PURE__ */ jsx(CurrentTimeLine, {}),
|
|
6962
|
-
layout.map(({ event, column, totalColumns }) => /* @__PURE__ */ jsx(
|
|
6963
|
-
TimedEvent,
|
|
6964
|
-
{
|
|
6965
|
-
event,
|
|
6966
|
-
category: categories[event.category ?? ""],
|
|
6967
|
-
column,
|
|
6968
|
-
totalColumns,
|
|
6969
|
-
onEventClick
|
|
6970
|
-
},
|
|
6971
|
-
event.id
|
|
6972
|
-
))
|
|
6973
|
-
]
|
|
6974
|
-
},
|
|
6975
|
-
i
|
|
6976
|
-
);
|
|
6977
|
-
})
|
|
6978
|
-
}
|
|
6979
|
-
)
|
|
6980
|
-
}
|
|
6981
|
-
) })
|
|
6982
|
-
] })
|
|
7256
|
+
list && /* @__PURE__ */ jsx(DayList, { day: list.day, events: getEventsForDay(barEvents, list.day), categories, anchor: list.anchor, onOpenEvent, onClose: () => setList(null) })
|
|
6983
7257
|
] });
|
|
6984
7258
|
}
|
|
6985
7259
|
var WEEKS_SHOWN = 6;
|
|
@@ -6990,7 +7264,6 @@ function DayCellWithPopover({
|
|
|
6990
7264
|
events,
|
|
6991
7265
|
categories,
|
|
6992
7266
|
selectedDate,
|
|
6993
|
-
onEventClick,
|
|
6994
7267
|
isEvenRow
|
|
6995
7268
|
}) {
|
|
6996
7269
|
const [open, setOpen] = useState(false);
|
|
@@ -7006,7 +7279,7 @@ function DayCellWithPopover({
|
|
|
7006
7279
|
const inMonth = day.getMonth() === month;
|
|
7007
7280
|
const dayEvents = inMonth ? getEventsForDay(events, day) : [];
|
|
7008
7281
|
const today = inMonth && isToday(day);
|
|
7009
|
-
const selected = inMonth && selectedDate &&
|
|
7282
|
+
const selected = inMonth && selectedDate && isSameDay(day, selectedDate);
|
|
7010
7283
|
const hasEvents = dayEvents.length > 0;
|
|
7011
7284
|
const handleMouseEnter = () => {
|
|
7012
7285
|
if (!hasEvents) return;
|
|
@@ -7028,7 +7301,6 @@ function DayCellWithPopover({
|
|
|
7028
7301
|
inMonth && "cursor-pointer hover:bg-[var(--ds-bg-muted)]",
|
|
7029
7302
|
!inMonth && "bg-[var(--ds-bg-muted)]/40",
|
|
7030
7303
|
inMonth && isEvenRow && !today && !selected && "bg-[var(--ds-bg-muted)]/20",
|
|
7031
|
-
today && "bg-[var(--ds-accent-subtle)]",
|
|
7032
7304
|
selected && !today && "bg-[var(--ds-accent-whisper)]"
|
|
7033
7305
|
),
|
|
7034
7306
|
children: [
|
|
@@ -7038,7 +7310,7 @@ function DayCellWithPopover({
|
|
|
7038
7310
|
{
|
|
7039
7311
|
className: cn(
|
|
7040
7312
|
"text-2xs leading-none z-[1]",
|
|
7041
|
-
today ? "
|
|
7313
|
+
today ? cn("w-5 h-5 inline-flex items-center justify-center rounded-[var(--ds-radius-full)]", TODAY_CIRCLE) : "text-[var(--ds-text-secondary)]"
|
|
7042
7314
|
),
|
|
7043
7315
|
children: day.getDate()
|
|
7044
7316
|
}
|
|
@@ -7062,16 +7334,8 @@ function DayCellWithPopover({
|
|
|
7062
7334
|
style: { top: pos.top, left: pos.left },
|
|
7063
7335
|
role: "tooltip",
|
|
7064
7336
|
children: [
|
|
7065
|
-
/* @__PURE__ */ jsx("p", { className: "text-2xs font-medium text-[var(--ds-text-muted)] px-ds-1 mb-ds-0.5", children:
|
|
7066
|
-
dayEvents.map((event) => /* @__PURE__ */ jsx(
|
|
7067
|
-
EventBar,
|
|
7068
|
-
{
|
|
7069
|
-
event,
|
|
7070
|
-
category: categories[event.category ?? ""],
|
|
7071
|
-
onClick: onEventClick
|
|
7072
|
-
},
|
|
7073
|
-
event.id
|
|
7074
|
-
))
|
|
7337
|
+
/* @__PURE__ */ jsx("p", { className: "text-2xs font-medium text-[var(--ds-text-muted)] px-ds-1 mb-ds-0.5", children: formatDayShort(day) }),
|
|
7338
|
+
dayEvents.map((event) => /* @__PURE__ */ jsx(EventBar, { event, category: categories[event.category ?? ""], inert: true }, event.id))
|
|
7075
7339
|
]
|
|
7076
7340
|
}
|
|
7077
7341
|
),
|
|
@@ -7088,7 +7352,6 @@ function MonthRow({
|
|
|
7088
7352
|
categories,
|
|
7089
7353
|
selectedDate,
|
|
7090
7354
|
onClick,
|
|
7091
|
-
onEventClick,
|
|
7092
7355
|
weekStartsOn
|
|
7093
7356
|
}) {
|
|
7094
7357
|
const grid = useMemo(
|
|
@@ -7106,7 +7369,7 @@ function MonthRow({
|
|
|
7106
7369
|
"border-r-[length:var(--ds-divider-width)] border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]"
|
|
7107
7370
|
),
|
|
7108
7371
|
onClick,
|
|
7109
|
-
children:
|
|
7372
|
+
children: monthName(month, "short")
|
|
7110
7373
|
}
|
|
7111
7374
|
),
|
|
7112
7375
|
flat.map((day, i) => /* @__PURE__ */ jsx(
|
|
@@ -7117,7 +7380,6 @@ function MonthRow({
|
|
|
7117
7380
|
events,
|
|
7118
7381
|
categories,
|
|
7119
7382
|
selectedDate,
|
|
7120
|
-
onEventClick,
|
|
7121
7383
|
isEvenRow: month % 2 === 0
|
|
7122
7384
|
},
|
|
7123
7385
|
i
|
|
@@ -7130,11 +7392,10 @@ function YearView({
|
|
|
7130
7392
|
categories,
|
|
7131
7393
|
selectedDate,
|
|
7132
7394
|
onMonthClick,
|
|
7133
|
-
onEventClick,
|
|
7134
7395
|
weekStartsOn
|
|
7135
7396
|
}) {
|
|
7136
7397
|
const year = date.getFullYear();
|
|
7137
|
-
const dayNames =
|
|
7398
|
+
const dayNames = weekdayNames(weekStartsOn, "narrow");
|
|
7138
7399
|
const repeatedHeaders = useMemo(() => {
|
|
7139
7400
|
const headers = [];
|
|
7140
7401
|
for (let w = 0; w < WEEKS_SHOWN; w++) {
|
|
@@ -7149,7 +7410,7 @@ function YearView({
|
|
|
7149
7410
|
{
|
|
7150
7411
|
className: "grid min-w-[700px]",
|
|
7151
7412
|
style: {
|
|
7152
|
-
gridTemplateColumns: `48px repeat(${COLS}, minmax(
|
|
7413
|
+
gridTemplateColumns: `48px repeat(${COLS}, minmax(24px, 1fr))`,
|
|
7153
7414
|
gridTemplateRows: `auto repeat(12, 36px)`
|
|
7154
7415
|
},
|
|
7155
7416
|
children: [
|
|
@@ -7162,7 +7423,7 @@ function YearView({
|
|
|
7162
7423
|
"bg-[var(--ds-bg-muted)] border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]",
|
|
7163
7424
|
h.isWeekStart && "border-l-[length:var(--ds-divider-width)]"
|
|
7164
7425
|
),
|
|
7165
|
-
children: h.label
|
|
7426
|
+
children: h.label
|
|
7166
7427
|
},
|
|
7167
7428
|
i
|
|
7168
7429
|
)),
|
|
@@ -7175,7 +7436,6 @@ function YearView({
|
|
|
7175
7436
|
categories,
|
|
7176
7437
|
selectedDate,
|
|
7177
7438
|
onClick: () => onMonthClick(month),
|
|
7178
|
-
onEventClick,
|
|
7179
7439
|
weekStartsOn
|
|
7180
7440
|
},
|
|
7181
7441
|
month
|
|
@@ -7184,191 +7444,83 @@ function YearView({
|
|
|
7184
7444
|
}
|
|
7185
7445
|
) });
|
|
7186
7446
|
}
|
|
7187
|
-
function
|
|
7188
|
-
|
|
7189
|
-
|
|
7190
|
-
|
|
7191
|
-
|
|
7192
|
-
|
|
7193
|
-
|
|
7194
|
-
|
|
7195
|
-
|
|
7196
|
-
const
|
|
7197
|
-
const
|
|
7198
|
-
|
|
7199
|
-
|
|
7200
|
-
|
|
7201
|
-
|
|
7202
|
-
|
|
7203
|
-
|
|
7447
|
+
function CompactMonthView({ date, events, categories, selectedDate, onDayClick, onOpenEvent, onNavigate, weekStartsOn }) {
|
|
7448
|
+
const weeks = useMemo(() => getMonthGrid(date.getFullYear(), date.getMonth(), weekStartsOn), [date, weekStartsOn]);
|
|
7449
|
+
const names = { narrow: weekdayNames(weekStartsOn, "narrow"), long: weekdayNames(weekStartsOn, "long") };
|
|
7450
|
+
const currentMonth = date.getMonth();
|
|
7451
|
+
const gridRef = useRef(null);
|
|
7452
|
+
const [list, setList] = useState(null);
|
|
7453
|
+
const inMonth = (d) => !!d && d.getMonth() === currentMonth && d.getFullYear() === date.getFullYear();
|
|
7454
|
+
const fallback = inMonth(selectedDate) ? selectedDate : inMonth(/* @__PURE__ */ new Date()) ? /* @__PURE__ */ new Date() : new Date(date.getFullYear(), currentMonth, 1);
|
|
7455
|
+
const [activeDay, setActiveDay] = useState(fallback);
|
|
7456
|
+
const active = inMonth(activeDay) ? activeDay : fallback;
|
|
7457
|
+
const grid = useGridKeyboard({
|
|
7458
|
+
container: gridRef,
|
|
7459
|
+
active,
|
|
7460
|
+
setActive: (d) => {
|
|
7461
|
+
setActiveDay(d);
|
|
7462
|
+
if (!inMonth(d)) onNavigate(d);
|
|
7463
|
+
},
|
|
7464
|
+
keyOf: dayKey,
|
|
7465
|
+
move: (from, e) => moveDay(from, e.key, e.shiftKey, weekStartsOn)
|
|
7204
7466
|
});
|
|
7205
|
-
|
|
7206
|
-
|
|
7207
|
-
|
|
7208
|
-
|
|
7209
|
-
|
|
7210
|
-
|
|
7211
|
-
|
|
7212
|
-
|
|
7213
|
-
|
|
7214
|
-
|
|
7215
|
-
|
|
7216
|
-
|
|
7217
|
-
|
|
7218
|
-
|
|
7219
|
-
|
|
7220
|
-
|
|
7221
|
-
|
|
7222
|
-
|
|
7223
|
-
|
|
7224
|
-
|
|
7225
|
-
setOpen((prev) => !prev);
|
|
7226
|
-
}
|
|
7227
|
-
};
|
|
7228
|
-
useEffect(() => {
|
|
7229
|
-
if (!open) return;
|
|
7230
|
-
const onKey = (e) => {
|
|
7231
|
-
if (e.key !== "Escape" || e.defaultPrevented || !isTop()) return;
|
|
7232
|
-
e.preventDefault();
|
|
7233
|
-
setOpen(false);
|
|
7234
|
-
};
|
|
7235
|
-
const onClick = (e) => {
|
|
7236
|
-
const t = e.target;
|
|
7237
|
-
if (cellRef.current?.contains(t) || floatingRef.current?.contains(t)) return;
|
|
7238
|
-
setOpen(false);
|
|
7239
|
-
};
|
|
7240
|
-
document.addEventListener("keydown", onKey);
|
|
7241
|
-
document.addEventListener("mousedown", onClick);
|
|
7242
|
-
return () => {
|
|
7243
|
-
document.removeEventListener("keydown", onKey);
|
|
7244
|
-
document.removeEventListener("mousedown", onClick);
|
|
7245
|
-
};
|
|
7246
|
-
}, [open, isTop]);
|
|
7247
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7248
|
-
/* @__PURE__ */ jsxs(
|
|
7249
|
-
"button",
|
|
7250
|
-
{
|
|
7251
|
-
ref: cellRef,
|
|
7252
|
-
type: "button",
|
|
7253
|
-
onClick: handleClick,
|
|
7254
|
-
onMouseEnter: handleMouseEnter,
|
|
7255
|
-
onMouseLeave: handleMouseLeave,
|
|
7256
|
-
className: cn(
|
|
7257
|
-
"flex flex-col items-center justify-center py-ds-1.5 rounded-[var(--ds-radius-sm)] cursor-pointer transition-colors",
|
|
7258
|
-
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
7259
|
-
!isCurrentMonth && "opacity-30",
|
|
7260
|
-
selected && "bg-[var(--ds-accent-subtle)]",
|
|
7261
|
-
!selected && "hover:bg-[var(--ds-bg-muted)]"
|
|
7262
|
-
),
|
|
7263
|
-
children: [
|
|
7264
|
-
/* @__PURE__ */ jsx(
|
|
7265
|
-
"span",
|
|
7266
|
-
{
|
|
7267
|
-
className: cn(
|
|
7268
|
-
"text-sm w-7 h-7 flex items-center justify-center rounded-[var(--ds-radius-full)]",
|
|
7269
|
-
today ? "bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] text-[var(--ds-text-on-primary)] font-bold" : "text-[var(--ds-text-primary)]"
|
|
7270
|
-
),
|
|
7271
|
-
children: day.getDate()
|
|
7272
|
-
}
|
|
7273
|
-
),
|
|
7274
|
-
/* @__PURE__ */ jsx("div", { className: "flex gap-ds-0.5 mt-ds-0.5 h-[6px] items-center", children: eventColors.map((color, i) => /* @__PURE__ */ jsx(
|
|
7275
|
-
"span",
|
|
7276
|
-
{
|
|
7277
|
-
className: "w-1.5 h-1.5 rounded-[var(--ds-radius-full)]",
|
|
7278
|
-
style: { backgroundColor: color }
|
|
7467
|
+
return /* @__PURE__ */ jsxs("div", { style: { padding: "var(--ds-space-3) var(--ds-space-2.5)" }, children: [
|
|
7468
|
+
/* @__PURE__ */ jsxs("div", { ref: gridRef, role: "grid", "aria-label": formatMonthYear(date), onKeyDown: grid.onKeyDown, className: "flex flex-col gap-y-ds-0.5", children: [
|
|
7469
|
+
/* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 mb-ds-1", children: names.narrow.map((name, i) => /* @__PURE__ */ jsx("div", { role: "columnheader", "aria-label": names.long[i], className: "text-center text-xs font-medium text-[var(--ds-text-muted)] py-ds-1.5", children: name }, i)) }),
|
|
7470
|
+
weeks.map((week) => /* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7", children: week.map((day) => {
|
|
7471
|
+
const isCurrentMonth = day.getMonth() === currentMonth;
|
|
7472
|
+
const dayEvents = isCurrentMonth ? getEventsForDay(events, day) : [];
|
|
7473
|
+
const today = isCurrentMonth && isToday(day);
|
|
7474
|
+
const selected = isCurrentMonth && !!selectedDate && isSameDay(day, selectedDate);
|
|
7475
|
+
return /* @__PURE__ */ jsxs(
|
|
7476
|
+
"button",
|
|
7477
|
+
{
|
|
7478
|
+
type: "button",
|
|
7479
|
+
role: "gridcell",
|
|
7480
|
+
"data-grid-key": dayKey(day),
|
|
7481
|
+
tabIndex: grid.tabIndexOf(day),
|
|
7482
|
+
"aria-label": dayEvents.length ? `${formatDayLong(day)}, ${dayEvents.length} ${dayEvents.length === 1 ? "event" : "events"}` : formatDayLong(day),
|
|
7483
|
+
"aria-selected": selected,
|
|
7484
|
+
"aria-current": today ? "date" : void 0,
|
|
7485
|
+
onFocus: () => {
|
|
7486
|
+
if (!isSameDay(day, active)) setActiveDay(day);
|
|
7279
7487
|
},
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
|
|
7284
|
-
|
|
7285
|
-
|
|
7286
|
-
|
|
7287
|
-
|
|
7288
|
-
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
7301
|
-
|
|
7302
|
-
role: "tooltip",
|
|
7303
|
-
children: [
|
|
7304
|
-
/* @__PURE__ */ jsx("p", { className: "text-2xs font-medium text-[var(--ds-text-muted)] px-ds-1 mb-ds-0.5", children: day.toLocaleDateString(formatLocale(), { weekday: "short", month: "short", day: "numeric" }) }),
|
|
7305
|
-
dayEvents.map((event) => /* @__PURE__ */ jsx(
|
|
7306
|
-
EventBar,
|
|
7307
|
-
{
|
|
7308
|
-
event,
|
|
7309
|
-
category: categories[event.category ?? ""],
|
|
7310
|
-
onClick: onEventClick
|
|
7311
|
-
},
|
|
7312
|
-
event.id
|
|
7313
|
-
))
|
|
7314
|
-
]
|
|
7315
|
-
}
|
|
7316
|
-
),
|
|
7317
|
-
document.body
|
|
7318
|
-
)
|
|
7319
|
-
] });
|
|
7320
|
-
}
|
|
7321
|
-
function CompactMonthView({
|
|
7322
|
-
date,
|
|
7323
|
-
events,
|
|
7324
|
-
categories,
|
|
7325
|
-
selectedDate,
|
|
7326
|
-
onDayClick,
|
|
7327
|
-
onEventClick,
|
|
7328
|
-
weekStartsOn
|
|
7329
|
-
}) {
|
|
7330
|
-
const weeks = useMemo(
|
|
7331
|
-
() => getMonthGrid(date.getFullYear(), date.getMonth(), weekStartsOn),
|
|
7332
|
-
[date, weekStartsOn]
|
|
7333
|
-
);
|
|
7334
|
-
const dayNames = useMemo(() => getOrderedDayNames(weekStartsOn), [weekStartsOn]);
|
|
7335
|
-
const currentMonth = date.getMonth();
|
|
7336
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", style: { padding: "var(--ds-space-3) var(--ds-space-2.5)" }, children: [
|
|
7337
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 mb-ds-1.5", children: dayNames.map((name) => /* @__PURE__ */ jsx(
|
|
7338
|
-
"div",
|
|
7339
|
-
{
|
|
7340
|
-
className: "text-center text-xs font-medium text-[var(--ds-text-muted)] py-ds-1.5",
|
|
7341
|
-
children: name[0]
|
|
7342
|
-
},
|
|
7343
|
-
name
|
|
7344
|
-
)) }),
|
|
7345
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 gap-y-ds-0.5", children: weeks.map(
|
|
7346
|
-
(week, wi) => week.map((day, di) => /* @__PURE__ */ jsx(
|
|
7347
|
-
CompactDayCell,
|
|
7348
|
-
{
|
|
7349
|
-
day,
|
|
7350
|
-
isCurrentMonth: day.getMonth() === currentMonth,
|
|
7351
|
-
events,
|
|
7352
|
-
categories,
|
|
7353
|
-
selectedDate,
|
|
7354
|
-
onDayClick,
|
|
7355
|
-
onEventClick
|
|
7356
|
-
},
|
|
7357
|
-
`${wi}-${di}`
|
|
7358
|
-
))
|
|
7359
|
-
) })
|
|
7488
|
+
onClick: (e) => {
|
|
7489
|
+
onDayClick(day);
|
|
7490
|
+
const anchor = e.currentTarget;
|
|
7491
|
+
if (dayEvents.length) setList((cur) => cur && isSameDay(cur.day, day) ? null : { day, anchor });
|
|
7492
|
+
},
|
|
7493
|
+
className: cn(
|
|
7494
|
+
"flex flex-col items-center justify-center py-ds-1.5 rounded-[var(--ds-radius-sm)] cursor-pointer transition-colors",
|
|
7495
|
+
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
7496
|
+
!isCurrentMonth && "opacity-30",
|
|
7497
|
+
selected && "bg-[var(--ds-accent-subtle)]",
|
|
7498
|
+
!selected && "hover:bg-[var(--ds-bg-muted)]"
|
|
7499
|
+
),
|
|
7500
|
+
children: [
|
|
7501
|
+
/* @__PURE__ */ jsx("span", { className: cn("text-sm w-7 h-7 flex items-center justify-center rounded-[var(--ds-radius-full)]", today ? TODAY_CIRCLE : "text-[var(--ds-text-primary)]"), children: day.getDate() }),
|
|
7502
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "flex gap-ds-0.5 mt-ds-0.5 h-[6px] items-center", children: dayEvents.slice(0, 3).map((event) => /* @__PURE__ */ jsx("span", { className: "w-1.5 h-1.5 rounded-[var(--ds-radius-full)]", style: { backgroundColor: eventColours(categories[event.category ?? ""]).edge } }, event.id)) })
|
|
7503
|
+
]
|
|
7504
|
+
},
|
|
7505
|
+
dayKey(day)
|
|
7506
|
+
);
|
|
7507
|
+
}) }, dayKey(week[0])))
|
|
7508
|
+
] }),
|
|
7509
|
+
list && /* @__PURE__ */ jsx(DayList, { day: list.day, events: getEventsForDay(events, list.day), categories, anchor: list.anchor, onOpenEvent, onClose: () => setList(null) })
|
|
7360
7510
|
] });
|
|
7361
7511
|
}
|
|
7362
7512
|
|
|
7363
7513
|
// ../../showcase/src/components/Calendar/types.ts
|
|
7364
7514
|
var DEFAULT_CATEGORIES = {
|
|
7365
|
-
work: { color: "
|
|
7366
|
-
personal: { color:
|
|
7367
|
-
meeting: { color:
|
|
7368
|
-
deadline: { color:
|
|
7369
|
-
travel: { color:
|
|
7370
|
-
social: { color:
|
|
7515
|
+
work: { color: "accent", label: "Work" },
|
|
7516
|
+
personal: { color: 1, label: "Personal" },
|
|
7517
|
+
meeting: { color: 2, label: "Meeting" },
|
|
7518
|
+
deadline: { color: 3, label: "Deadline" },
|
|
7519
|
+
travel: { color: 4, label: "Travel" },
|
|
7520
|
+
social: { color: 5, label: "Social" }
|
|
7371
7521
|
};
|
|
7522
|
+
var notADate = (d) => d !== void 0 && Number.isNaN(new Date(d).getTime());
|
|
7523
|
+
var WEEK_FLOOR = 160 + 4 * HOUR_HEIGHT;
|
|
7372
7524
|
function useControllableState(controlled, defaultValue, onChange) {
|
|
7373
7525
|
const [internal, setInternal] = useState(defaultValue);
|
|
7374
7526
|
const value = controlled !== void 0 ? controlled : internal;
|
|
@@ -7448,9 +7600,7 @@ function MonthDropdown({
|
|
|
7448
7600
|
"pl-ds-3 pr-ds-2 py-ds-1"
|
|
7449
7601
|
),
|
|
7450
7602
|
children: [
|
|
7451
|
-
|
|
7452
|
-
" ",
|
|
7453
|
-
currentYear,
|
|
7603
|
+
formatMonthYear(currentDate),
|
|
7454
7604
|
/* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: 12, className: cn("transition-transform", open && "rotate-180") })
|
|
7455
7605
|
]
|
|
7456
7606
|
}
|
|
@@ -7492,7 +7642,7 @@ function MonthDropdown({
|
|
|
7492
7642
|
}
|
|
7493
7643
|
)
|
|
7494
7644
|
] }),
|
|
7495
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-ds-1", children:
|
|
7645
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-ds-1", children: Array.from({ length: 12 }, (_, i) => monthName(i, "short")).map((name, i) => {
|
|
7496
7646
|
const isActive2 = i === currentMonth && browseYear === currentYear;
|
|
7497
7647
|
return /* @__PURE__ */ jsx(
|
|
7498
7648
|
"button",
|
|
@@ -7510,7 +7660,7 @@ function MonthDropdown({
|
|
|
7510
7660
|
},
|
|
7511
7661
|
children: name
|
|
7512
7662
|
},
|
|
7513
|
-
|
|
7663
|
+
i
|
|
7514
7664
|
);
|
|
7515
7665
|
}) })
|
|
7516
7666
|
]
|
|
@@ -7663,6 +7813,7 @@ function Calendar({
|
|
|
7663
7813
|
onDateRangeChange,
|
|
7664
7814
|
onEventClick,
|
|
7665
7815
|
onDayClick,
|
|
7816
|
+
eventActions,
|
|
7666
7817
|
categories = DEFAULT_CATEGORIES,
|
|
7667
7818
|
weekStartsOn = 1,
|
|
7668
7819
|
size = "default",
|
|
@@ -7673,14 +7824,21 @@ function Calendar({
|
|
|
7673
7824
|
defaultView,
|
|
7674
7825
|
onViewChange
|
|
7675
7826
|
);
|
|
7827
|
+
const today = useMemo(() => /* @__PURE__ */ new Date(), []);
|
|
7676
7828
|
const [currentDate, setCurrentDate] = useControllableState(
|
|
7677
|
-
controlledDate,
|
|
7678
|
-
defaultDate
|
|
7829
|
+
notADate(controlledDate) ? today : controlledDate,
|
|
7830
|
+
defaultDate !== void 0 && !notADate(defaultDate) ? defaultDate : today,
|
|
7679
7831
|
onDateChange
|
|
7680
7832
|
);
|
|
7833
|
+
const dateUnreadable = notADate(controlledDate) || notADate(defaultDate);
|
|
7834
|
+
useEffect(() => {
|
|
7835
|
+
if (dateUnreadable) warnOnce("Calendar", "its date (or defaultDate) isn't a date, so it shows today: pass a Date, or a date string Date reads.");
|
|
7836
|
+
}, [dateUnreadable]);
|
|
7681
7837
|
const [selectedDate, setSelectedDate] = useState(null);
|
|
7682
7838
|
const [isNarrow, setIsNarrow] = useState(false);
|
|
7839
|
+
const rootRef = useRef(null);
|
|
7683
7840
|
const containerRef = useCallback((node) => {
|
|
7841
|
+
rootRef.current = node;
|
|
7684
7842
|
if (!node) return;
|
|
7685
7843
|
const ro = new ResizeObserver((entries) => {
|
|
7686
7844
|
const width = entries[0]?.contentRect.width ?? 0;
|
|
@@ -7689,10 +7847,44 @@ function Calendar({
|
|
|
7689
7847
|
ro.observe(node);
|
|
7690
7848
|
return () => ro.disconnect();
|
|
7691
7849
|
}, []);
|
|
7692
|
-
const
|
|
7693
|
-
|
|
7694
|
-
|
|
7695
|
-
);
|
|
7850
|
+
const fillRaw = useFillHeight(rootRef, size !== "compact" && currentView === "week");
|
|
7851
|
+
const fill2 = fillRaw !== null && fillRaw >= WEEK_FLOOR ? fillRaw : null;
|
|
7852
|
+
const inPane = useContext(FillContext) && currentView === "week";
|
|
7853
|
+
const [openEvent, setOpenEvent] = useState(null);
|
|
7854
|
+
const openCard = useCallback((event, from) => {
|
|
7855
|
+
if (onEventClick) {
|
|
7856
|
+
onEventClick(event);
|
|
7857
|
+
return;
|
|
7858
|
+
}
|
|
7859
|
+
setOpenEvent((cur) => cur && cur.event.id === event.id && cur.anchor === from ? null : { event, anchor: from });
|
|
7860
|
+
}, [onEventClick]);
|
|
7861
|
+
const actionsHidden = !!onEventClick && !!eventActions;
|
|
7862
|
+
useEffect(() => {
|
|
7863
|
+
if (actionsHidden) warnOnce("Calendar", "eventActions are never shown while onEventClick is set: the page opens a surface of its own for an event, so no card shows. Pass eventActions for the Calendar's card, or onEventClick for your own (Sprint 25.18).");
|
|
7864
|
+
}, [actionsHidden]);
|
|
7865
|
+
const shownKey = `${currentView}|${currentDate.toDateString()}`;
|
|
7866
|
+
const [cardShownKey, setCardShownKey] = useState(shownKey);
|
|
7867
|
+
if (cardShownKey !== shownKey) {
|
|
7868
|
+
setCardShownKey(shownKey);
|
|
7869
|
+
if (openEvent) setOpenEvent(null);
|
|
7870
|
+
}
|
|
7871
|
+
const { stableEvents, unreadable } = useMemo(() => {
|
|
7872
|
+
const read = [];
|
|
7873
|
+
const left = [];
|
|
7874
|
+
for (const e of events) {
|
|
7875
|
+
const start = new Date(e.start);
|
|
7876
|
+
if (Number.isNaN(start.getTime())) {
|
|
7877
|
+
left.push(String(e.id));
|
|
7878
|
+
continue;
|
|
7879
|
+
}
|
|
7880
|
+
const end = e.end ? new Date(e.end) : void 0;
|
|
7881
|
+
read.push({ ...e, start, end: end && !Number.isNaN(end.getTime()) ? end : void 0 });
|
|
7882
|
+
}
|
|
7883
|
+
return { stableEvents: read, unreadable: left.join(", ") };
|
|
7884
|
+
}, [events]);
|
|
7885
|
+
useEffect(() => {
|
|
7886
|
+
if (unreadable) warnOnce("Calendar", `events with a start that isn't a date aren't drawn (${unreadable}): give each a Date, or a date string Date reads.`);
|
|
7887
|
+
}, [unreadable]);
|
|
7696
7888
|
useEffect(() => {
|
|
7697
7889
|
if (!onDateRangeChange) return;
|
|
7698
7890
|
let start, end;
|
|
@@ -7725,9 +7917,10 @@ function Calendar({
|
|
|
7725
7917
|
setSelectedDate(/* @__PURE__ */ new Date());
|
|
7726
7918
|
}, [setCurrentDate]);
|
|
7727
7919
|
const handleDayClick = useCallback(
|
|
7728
|
-
(date) => {
|
|
7920
|
+
(date, detail) => {
|
|
7729
7921
|
setSelectedDate(date);
|
|
7730
|
-
onDayClick?.(date);
|
|
7922
|
+
if (detail) onDayClick?.(date, detail);
|
|
7923
|
+
else onDayClick?.(date);
|
|
7731
7924
|
},
|
|
7732
7925
|
[onDayClick]
|
|
7733
7926
|
);
|
|
@@ -7742,10 +7935,24 @@ function Calendar({
|
|
|
7742
7935
|
if (currentView === "week") return formatWeekRange(currentDate, weekStartsOn);
|
|
7743
7936
|
return void 0;
|
|
7744
7937
|
}, [currentView, currentDate, weekStartsOn]);
|
|
7938
|
+
const live = openEvent && stableEvents.find((e) => e.id === openEvent.event.id);
|
|
7939
|
+
const card = openEvent && live ? /* @__PURE__ */ jsx(
|
|
7940
|
+
EventCard,
|
|
7941
|
+
{
|
|
7942
|
+
event: live,
|
|
7943
|
+
category: categories[live.category ?? ""],
|
|
7944
|
+
anchor: openEvent.anchor,
|
|
7945
|
+
actions: typeof eventActions === "function" ? eventActions(live) : eventActions ?? [],
|
|
7946
|
+
onClose: () => setOpenEvent(null),
|
|
7947
|
+
fallbackFocus: () => rootRef.current?.querySelector('[role="gridcell"][tabindex="0"]')
|
|
7948
|
+
},
|
|
7949
|
+
openEvent.event.id
|
|
7950
|
+
) : null;
|
|
7745
7951
|
if (size === "compact") {
|
|
7746
7952
|
return /* @__PURE__ */ jsxs(
|
|
7747
7953
|
"div",
|
|
7748
7954
|
{
|
|
7955
|
+
ref: containerRef,
|
|
7749
7956
|
className: cn(
|
|
7750
7957
|
"flex flex-col",
|
|
7751
7958
|
"bg-[var(--ds-bg-surface)]",
|
|
@@ -7775,16 +7982,12 @@ function Calendar({
|
|
|
7775
7982
|
children: /* @__PURE__ */ jsx(Icon, { name: "chevron-left", size: 16 })
|
|
7776
7983
|
}
|
|
7777
7984
|
),
|
|
7778
|
-
/* @__PURE__ */
|
|
7985
|
+
/* @__PURE__ */ jsx(
|
|
7779
7986
|
"button",
|
|
7780
7987
|
{
|
|
7781
7988
|
onClick: goToToday,
|
|
7782
7989
|
className: "text-sm font-medium text-[var(--ds-text-primary)] hover:text-[var(--ds-accent-primary)] transition-colors cursor-pointer px-ds-2",
|
|
7783
|
-
children:
|
|
7784
|
-
MONTH_NAMES[currentDate.getMonth()],
|
|
7785
|
-
" ",
|
|
7786
|
-
currentDate.getFullYear()
|
|
7787
|
-
]
|
|
7990
|
+
children: formatMonthYear(currentDate)
|
|
7788
7991
|
}
|
|
7789
7992
|
),
|
|
7790
7993
|
/* @__PURE__ */ jsx(
|
|
@@ -7807,10 +8010,12 @@ function Calendar({
|
|
|
7807
8010
|
categories,
|
|
7808
8011
|
selectedDate,
|
|
7809
8012
|
onDayClick: handleDayClick,
|
|
7810
|
-
|
|
8013
|
+
onOpenEvent: openCard,
|
|
8014
|
+
onNavigate: setCurrentDate,
|
|
7811
8015
|
weekStartsOn
|
|
7812
8016
|
}
|
|
7813
|
-
)
|
|
8017
|
+
),
|
|
8018
|
+
card
|
|
7814
8019
|
]
|
|
7815
8020
|
}
|
|
7816
8021
|
);
|
|
@@ -7819,6 +8024,7 @@ function Calendar({
|
|
|
7819
8024
|
"div",
|
|
7820
8025
|
{
|
|
7821
8026
|
ref: containerRef,
|
|
8027
|
+
"data-fill": fill2 != null ? "" : void 0,
|
|
7822
8028
|
className: cn(
|
|
7823
8029
|
"flex flex-col",
|
|
7824
8030
|
"bg-[var(--ds-bg-surface)]",
|
|
@@ -7826,8 +8032,10 @@ function Calendar({
|
|
|
7826
8032
|
"rounded-[var(--ds-radius-lg)]",
|
|
7827
8033
|
"shadow-[var(--ds-shadow-sm)]",
|
|
7828
8034
|
"overflow-hidden",
|
|
8035
|
+
inPane && "h-full min-h-0",
|
|
7829
8036
|
className
|
|
7830
8037
|
),
|
|
8038
|
+
style: fill2 != null ? { height: fill2 } : void 0,
|
|
7831
8039
|
children: [
|
|
7832
8040
|
isNarrow ? /* @__PURE__ */ jsxs(
|
|
7833
8041
|
"div",
|
|
@@ -7886,7 +8094,7 @@ function Calendar({
|
|
|
7886
8094
|
]
|
|
7887
8095
|
}
|
|
7888
8096
|
),
|
|
7889
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-h-0", style: { minHeight: currentView === "week" ? 420 : currentView === "month" ? isNarrow ? 360 : 500 : void 0 }, children: [
|
|
8097
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-h-0", style: { minHeight: currentView === "week" ? fill2 != null || inPane ? void 0 : 420 : currentView === "month" ? isNarrow ? 360 : 500 : void 0 }, children: [
|
|
7890
8098
|
currentView === "month" && /* @__PURE__ */ jsx(
|
|
7891
8099
|
MonthView,
|
|
7892
8100
|
{
|
|
@@ -7895,7 +8103,9 @@ function Calendar({
|
|
|
7895
8103
|
categories,
|
|
7896
8104
|
selectedDate,
|
|
7897
8105
|
onDayClick: handleDayClick,
|
|
7898
|
-
|
|
8106
|
+
canStartEvent: !!onDayClick,
|
|
8107
|
+
onOpenEvent: openCard,
|
|
8108
|
+
onNavigate: setCurrentDate,
|
|
7899
8109
|
weekStartsOn
|
|
7900
8110
|
}
|
|
7901
8111
|
),
|
|
@@ -7907,7 +8117,8 @@ function Calendar({
|
|
|
7907
8117
|
categories,
|
|
7908
8118
|
selectedDate,
|
|
7909
8119
|
onDayClick: handleDayClick,
|
|
7910
|
-
|
|
8120
|
+
onOpenEvent: openCard,
|
|
8121
|
+
onNavigate: setCurrentDate,
|
|
7911
8122
|
weekStartsOn
|
|
7912
8123
|
}
|
|
7913
8124
|
),
|
|
@@ -7919,11 +8130,11 @@ function Calendar({
|
|
|
7919
8130
|
categories,
|
|
7920
8131
|
selectedDate,
|
|
7921
8132
|
onMonthClick: handleMonthClick,
|
|
7922
|
-
weekStartsOn
|
|
7923
|
-
onEventClick
|
|
8133
|
+
weekStartsOn
|
|
7924
8134
|
}
|
|
7925
8135
|
)
|
|
7926
|
-
] })
|
|
8136
|
+
] }),
|
|
8137
|
+
card
|
|
7927
8138
|
]
|
|
7928
8139
|
}
|
|
7929
8140
|
);
|
|
@@ -9763,9 +9974,9 @@ var StackedList = forwardRef(function StackedList2({
|
|
|
9763
9974
|
] });
|
|
9764
9975
|
});
|
|
9765
9976
|
var TIME_ZOOMS = ["day", "week", "month", "quarter"];
|
|
9766
|
-
var
|
|
9977
|
+
var DAY_MS2 = 864e5;
|
|
9767
9978
|
var DATE_ONLY2 = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
9768
|
-
var utcDay = (y, m, d) => Math.round(Date.UTC(y, m, d) /
|
|
9979
|
+
var utcDay = (y, m, d) => Math.round(Date.UTC(y, m, d) / DAY_MS2);
|
|
9769
9980
|
function dayOfDate(d) {
|
|
9770
9981
|
const t = d.getTime();
|
|
9771
9982
|
if (Number.isNaN(t)) return NaN;
|
|
@@ -9774,7 +9985,7 @@ function dayOfDate(d) {
|
|
|
9774
9985
|
first.setHours(0, 0, 0, 0);
|
|
9775
9986
|
if (first.getTime() === t) return day;
|
|
9776
9987
|
const ms = ((d.getHours() * 60 + d.getMinutes()) * 60 + d.getSeconds()) * 1e3 + d.getMilliseconds();
|
|
9777
|
-
return day + ms /
|
|
9988
|
+
return day + ms / DAY_MS2;
|
|
9778
9989
|
}
|
|
9779
9990
|
function dayOf(value) {
|
|
9780
9991
|
if (typeof value === "number") return Number.isFinite(value) ? value : NaN;
|
|
@@ -9784,13 +9995,13 @@ function dayOf(value) {
|
|
|
9784
9995
|
if (!m) return dayOfDate(new Date(value));
|
|
9785
9996
|
const [y, mo, d] = [Number(m[1]), Number(m[2]) - 1, Number(m[3])];
|
|
9786
9997
|
const day = utcDay(y, mo, d);
|
|
9787
|
-
const back = new Date(day *
|
|
9998
|
+
const back = new Date(day * DAY_MS2);
|
|
9788
9999
|
return back.getUTCFullYear() === y && back.getUTCMonth() === mo && back.getUTCDate() === d ? day : NaN;
|
|
9789
10000
|
}
|
|
9790
10001
|
function dateOfDay(day) {
|
|
9791
10002
|
const whole = Math.floor(day);
|
|
9792
|
-
const u = new Date(whole *
|
|
9793
|
-
return new Date(u.getUTCFullYear(), u.getUTCMonth(), u.getUTCDate(), 0, 0, 0, Math.round((day - whole) *
|
|
10003
|
+
const u = new Date(whole * DAY_MS2);
|
|
10004
|
+
return new Date(u.getUTCFullYear(), u.getUTCMonth(), u.getUTCDate(), 0, 0, 0, Math.round((day - whole) * DAY_MS2));
|
|
9794
10005
|
}
|
|
9795
10006
|
function isWholeDay(value) {
|
|
9796
10007
|
return typeof value === "string" ? DATE_ONLY2.test(value.trim()) : Number.isInteger(dayOf(value));
|
|
@@ -9809,7 +10020,7 @@ function periodStart(unit, day, weekStartsOn) {
|
|
|
9809
10020
|
const d = Math.floor(day);
|
|
9810
10021
|
if (unit === "day") return d;
|
|
9811
10022
|
if (unit === "week") return d - (weekday(d) - weekStartsOn + 7) % 7;
|
|
9812
|
-
const u = new Date(d *
|
|
10023
|
+
const u = new Date(d * DAY_MS2);
|
|
9813
10024
|
const y = u.getUTCFullYear();
|
|
9814
10025
|
const m = u.getUTCMonth();
|
|
9815
10026
|
if (unit === "month") return utcDay(y, m, 1);
|
|
@@ -9819,7 +10030,7 @@ function periodStart(unit, day, weekStartsOn) {
|
|
|
9819
10030
|
function periodAfter(unit, start) {
|
|
9820
10031
|
if (unit === "day") return start + 1;
|
|
9821
10032
|
if (unit === "week") return start + 7;
|
|
9822
|
-
const u = new Date(start *
|
|
10033
|
+
const u = new Date(start * DAY_MS2);
|
|
9823
10034
|
const y = u.getUTCFullYear();
|
|
9824
10035
|
const m = u.getUTCMonth();
|
|
9825
10036
|
if (unit === "month") return utcDay(y, m + 1, 1);
|
|
@@ -9838,11 +10049,11 @@ function formatter(given, options) {
|
|
|
9838
10049
|
return f;
|
|
9839
10050
|
}
|
|
9840
10051
|
function format(day, locale, options) {
|
|
9841
|
-
return formatter(locale, options).format(new Date(day *
|
|
10052
|
+
return formatter(locale, options).format(new Date(day * DAY_MS2));
|
|
9842
10053
|
}
|
|
9843
10054
|
var pad22 = (n) => String(n).padStart(2, "0");
|
|
9844
10055
|
function keyOf(unit, day) {
|
|
9845
|
-
const u = new Date(day *
|
|
10056
|
+
const u = new Date(day * DAY_MS2);
|
|
9846
10057
|
const y = u.getUTCFullYear();
|
|
9847
10058
|
const m = u.getUTCMonth();
|
|
9848
10059
|
if (unit === "year") return String(y);
|
|
@@ -9857,7 +10068,7 @@ function labelsOf(unit, role, day, locale) {
|
|
|
9857
10068
|
else if (unit === "week") forms = [f({ day: "numeric", month: "short" }), f({ day: "numeric" })];
|
|
9858
10069
|
else if (unit === "month") {
|
|
9859
10070
|
forms = role === "major" ? [f({ month: "long", year: "numeric" }), f({ month: "short", year: "numeric" }), f({ month: "short" }), f({ month: "narrow" })] : [f({ month: "long" }), f({ month: "short" }), f({ month: "narrow" })];
|
|
9860
|
-
} else if (unit === "quarter") forms = [`Q${Math.floor(new Date(day *
|
|
10071
|
+
} else if (unit === "quarter") forms = [`Q${Math.floor(new Date(day * DAY_MS2).getUTCMonth() / 3) + 1}`];
|
|
9861
10072
|
else forms = [f({ year: "numeric" }), f({ year: "2-digit" })];
|
|
9862
10073
|
return forms;
|
|
9863
10074
|
}
|
|
@@ -9998,8 +10209,8 @@ function formatDateRange(start, end, words) {
|
|
|
9998
10209
|
const timed = !isWholeDay(start) || !isWholeDay(until);
|
|
9999
10210
|
const first = timed ? from : Math.floor(from);
|
|
10000
10211
|
const last = timed ? Math.max(from, stop) : Math.max(first, Math.ceil(stop) - 1);
|
|
10001
|
-
const a = new Date(first *
|
|
10002
|
-
const b = new Date(last *
|
|
10212
|
+
const a = new Date(first * DAY_MS2);
|
|
10213
|
+
const b = new Date(last * DAY_MS2);
|
|
10003
10214
|
const years = a.getUTCFullYear() !== b.getUTCFullYear() && day.year === void 0;
|
|
10004
10215
|
const f = formatter(locale, { ...day, ...years ? { year: "numeric" } : {}, ...timed ? time : {} });
|
|
10005
10216
|
return first === last ? f.format(a) : range(f, a, b, to ?? (english(f) ? " to " : void 0));
|
|
@@ -10276,9 +10487,9 @@ function TimeScaleHeader({ todayLabel = "Today", className }) {
|
|
|
10276
10487
|
}
|
|
10277
10488
|
var ZOOM_NAMES = { day: "Days", week: "Weeks", month: "Months", quarter: "Quarters" };
|
|
10278
10489
|
var SHADE_MIN = 4;
|
|
10279
|
-
var
|
|
10490
|
+
var INSET2 = 8;
|
|
10280
10491
|
var MIN_INSET = 2;
|
|
10281
|
-
var MIN_TITLE = 2 *
|
|
10492
|
+
var MIN_TITLE = 2 * INSET2 + 12;
|
|
10282
10493
|
var PHONE_BELOW = 640;
|
|
10283
10494
|
var MIN_LABEL = 112;
|
|
10284
10495
|
var ROW_HEIGHT = 40;
|
|
@@ -10632,7 +10843,7 @@ function TimeBar({ start, end, minWidth = 0, labels, children, className, style,
|
|
|
10632
10843
|
let label = null;
|
|
10633
10844
|
if (labels && hasLabels) {
|
|
10634
10845
|
const widths = labels.map(measure);
|
|
10635
|
-
const inset = Math.min(
|
|
10846
|
+
const inset = Math.min(INSET2, Math.max(MIN_INSET, (drawnWidth - borders.start - borders.end - Math.min(...widths)) / 2 - 0.5));
|
|
10636
10847
|
const fits = (i) => `clamp(0, calc((${inView} - ${widths[i] + 2 * inset} + 0.25) * 1000), 1)`;
|
|
10637
10848
|
const shows = (i) => i === 0 ? fits(0) : `calc(${[fits(i), ...labels.slice(0, i).map((_, j) => `(1 - ${fits(j)})`)].join(" * ")})`;
|
|
10638
10849
|
const named = props["aria-label"] !== void 0 || props["aria-labelledby"] !== void 0;
|
|
@@ -10647,7 +10858,7 @@ function TimeBar({ start, end, minWidth = 0, labels, children, className, style,
|
|
|
10647
10858
|
"data-time-bar-label": "",
|
|
10648
10859
|
"data-gs-clip": "",
|
|
10649
10860
|
className: "sticky flex min-w-0 items-center gap-ds-1 overflow-hidden whitespace-nowrap",
|
|
10650
|
-
style: { ...sticky, paddingInline:
|
|
10861
|
+
style: { ...sticky, paddingInline: INSET2, opacity: `clamp(0, calc((${inView} - ${MIN_TITLE}) * 1000), 1)` },
|
|
10651
10862
|
children: typeof children === "string" ? /* @__PURE__ */ jsx("span", { className: "truncate", children }) : children
|
|
10652
10863
|
}
|
|
10653
10864
|
);
|