gridsmith-ui 0.26.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +969 -0
- package/README.md +21 -5
- package/dist/charts.d.ts +2 -2
- package/dist/charts.js +58 -43
- package/dist/charts.js.map +1 -1
- package/dist/chat.js +4 -3
- package/dist/chat.js.map +1 -1
- package/dist/{chunk-CYN5O567.js → chunk-2CKSSWYG.js} +9 -5
- package/dist/chunk-2CKSSWYG.js.map +1 -0
- package/dist/chunk-3BRQRKDO.js +1 -0
- package/dist/chunk-3BRQRKDO.js.map +1 -1
- package/dist/{chunk-RWKCAKN3.js → chunk-5TUVX4B2.js} +6 -5
- package/dist/chunk-5TUVX4B2.js.map +1 -0
- package/dist/{chunk-X2HEV7FB.js → chunk-64TXZ4L7.js} +23 -33
- package/dist/chunk-64TXZ4L7.js.map +1 -0
- package/dist/chunk-7Q46JXSK.js +1 -0
- package/dist/chunk-7Q46JXSK.js.map +1 -1
- package/dist/chunk-CRQ6KCRD.js +1 -0
- package/dist/chunk-CRQ6KCRD.js.map +1 -1
- package/dist/{chunk-ZYVXV4WC.js → chunk-EKBWWA6P.js} +53 -6
- package/dist/chunk-EKBWWA6P.js.map +1 -0
- package/dist/chunk-HP7WUZPK.js +1 -0
- package/dist/chunk-HP7WUZPK.js.map +1 -1
- package/dist/{chunk-MYIJNVTK.js → chunk-IXR4UEF4.js} +5 -4
- package/dist/chunk-IXR4UEF4.js.map +1 -0
- package/dist/chunk-M2QRNBDQ.js +1 -0
- package/dist/chunk-M2QRNBDQ.js.map +1 -1
- package/dist/chunk-MD2EFMES.js +1 -0
- package/dist/chunk-MD2EFMES.js.map +1 -1
- package/dist/chunk-NRHIYS5W.js +1 -0
- package/dist/chunk-NRHIYS5W.js.map +1 -1
- package/dist/chunk-OTCEJN64.js +1 -0
- package/dist/chunk-OTCEJN64.js.map +1 -1
- package/dist/chunk-OYNUU346.js +78 -0
- package/dist/chunk-OYNUU346.js.map +1 -0
- package/dist/{chunk-EX64MN2U.js → chunk-PO65I3MQ.js} +4 -3
- package/dist/chunk-PO65I3MQ.js.map +1 -0
- package/dist/chunk-QM4SJKWV.js +1 -0
- package/dist/chunk-QM4SJKWV.js.map +1 -1
- package/dist/{chunk-KWLNEH53.js → chunk-R5NFCEZ3.js} +10 -7
- package/dist/chunk-R5NFCEZ3.js.map +1 -0
- package/dist/chunk-SFY2KMHG.js +1 -0
- package/dist/chunk-SFY2KMHG.js.map +1 -1
- package/dist/{chunk-HXVXJUGV.js → chunk-TJEV7YAY.js} +38 -10
- package/dist/chunk-TJEV7YAY.js.map +1 -0
- package/dist/chunk-WH2FUFAC.js +1 -0
- package/dist/chunk-WH2FUFAC.js.map +1 -1
- package/dist/chunk-XVB55M3N.js +1 -0
- package/dist/chunk-XVB55M3N.js.map +1 -1
- package/dist/chunk-ZI3OQDET.js +1 -0
- package/dist/chunk-ZI3OQDET.js.map +1 -1
- package/dist/data-grid.d.ts +1 -1
- package/dist/data-grid.js +5 -3
- package/dist/data-grid.js.map +1 -1
- package/dist/editor-mentions.js +2 -1
- package/dist/editor-mentions.js.map +1 -1
- package/dist/editor.js +3 -2
- package/dist/editor.js.map +1 -1
- package/dist/{feather-VFWLAILO.js → feather-FNBQ74RR.js} +10 -17
- package/dist/feather-FNBQ74RR.js.map +1 -0
- package/dist/{heroicons-H3Z7DFCF.js → heroicons-DODCSYWD.js} +9 -8
- package/dist/heroicons-DODCSYWD.js.map +1 -0
- package/dist/icons.d.ts +31 -4
- package/dist/icons.js +2 -1
- package/dist/icons.js.map +1 -1
- package/dist/index.d.ts +418 -65
- package/dist/index.js +1893 -838
- package/dist/index.js.map +1 -1
- package/dist/kanban.js +3 -2
- package/dist/kanban.js.map +1 -1
- package/dist/{lucide-MR32KM4G.js → lucide-ZWE3EPGP.js} +9 -8
- package/dist/lucide-ZWE3EPGP.js.map +1 -0
- package/dist/{phosphor-ABQQL5N5.js → phosphor-DIHPA4AJ.js} +9 -8
- package/dist/phosphor-DIHPA4AJ.js.map +1 -0
- package/dist/resizable.js +7 -5
- package/dist/resizable.js.map +1 -1
- package/dist/roots.css +25 -7
- package/dist/{tabler-ANUSY4D2.js → tabler-D3VYTSGI.js} +9 -8
- package/dist/tabler-D3VYTSGI.js.map +1 -0
- package/dist/tokens.css +11 -8
- package/dist/{use-pagination-BnKOnBdz.d.ts → use-pagination-BxcRlNQG.d.ts} +6 -0
- package/dist/utils.d.ts +275 -1
- package/dist/utils.js +875 -1
- package/dist/utils.js.map +1 -1
- package/dist/virtualized.d.ts +1 -1
- package/dist/virtualized.js +5 -3
- package/dist/virtualized.js.map +1 -1
- package/dist-static/tokens.css +11 -8
- package/package.json +5 -3
- package/dist/chunk-CYN5O567.js.map +0 -1
- package/dist/chunk-EX64MN2U.js.map +0 -1
- package/dist/chunk-HXVXJUGV.js.map +0 -1
- package/dist/chunk-KWLNEH53.js.map +0 -1
- package/dist/chunk-MYIJNVTK.js.map +0 -1
- package/dist/chunk-RWKCAKN3.js.map +0 -1
- package/dist/chunk-X2HEV7FB.js.map +0 -1
- package/dist/chunk-ZYVXV4WC.js.map +0 -1
- package/dist/feather-VFWLAILO.js.map +0 -1
- package/dist/heroicons-H3Z7DFCF.js.map +0 -1
- package/dist/lucide-MR32KM4G.js.map +0 -1
- package/dist/phosphor-ABQQL5N5.js.map +0 -1
- package/dist/tabler-ANUSY4D2.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,31 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
export {
|
|
4
|
-
import {
|
|
5
|
-
export {
|
|
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
|
-
import { Skeleton, TITLE_TEXT, formatLocale } from './chunk-X2HEV7FB.js';
|
|
9
|
-
export { Skeleton } from './chunk-X2HEV7FB.js';
|
|
1
|
+
"use client";
|
|
2
|
+
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-R5NFCEZ3.js';
|
|
3
|
+
export { AppShell, Breadcrumbs, Drawer, SkipLink, useAppShell, useUnsavedChanges } from './chunk-R5NFCEZ3.js';
|
|
4
|
+
import { Skeleton, TITLE_TEXT, useFormatLocale, useHydrated, useToday, LocaleContext } from './chunk-64TXZ4L7.js';
|
|
5
|
+
export { Skeleton, useFormatLocale, useHydrated } from './chunk-64TXZ4L7.js';
|
|
10
6
|
import { useScrollEdges, EDGE_FADE } from './chunk-3BRQRKDO.js';
|
|
7
|
+
import { Avatar, foldForSearch, useActiveOptionInView, shownMentions, matchMentions, mentionOptionId, MentionList, initialsOf } from './chunk-5TUVX4B2.js';
|
|
8
|
+
export { Avatar } from './chunk-5TUVX4B2.js';
|
|
9
|
+
import { Link } from './chunk-IXR4UEF4.js';
|
|
10
|
+
export { CodeBlock, Divider, Link } from './chunk-IXR4UEF4.js';
|
|
11
|
+
import { useFillHeight, FillContext, useKeyboardScroll, FOCUS_INSET } from './chunk-SFY2KMHG.js';
|
|
12
|
+
import { Badge } from './chunk-PO65I3MQ.js';
|
|
13
|
+
export { Badge } from './chunk-PO65I3MQ.js';
|
|
14
|
+
import { inferColumnKinds, useCardsSwitch, CARDS_BELOW, kindOfRenderedText, CardValue } from './chunk-OTCEJN64.js';
|
|
15
|
+
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, OutsideField, NumberInput, InlineFieldError, Label, AddAnotherRowCtx, Field } from './chunk-2CKSSWYG.js';
|
|
16
|
+
export { Dropdown, Field, InlineFieldError, Input, Label, NumberInput, Pagination, Popover, Textarea, Toggle, usePagination } from './chunk-2CKSSWYG.js';
|
|
17
|
+
import { Button, ControlSizeContext, triggerType, Spinner, useShellPreferences, PREFERENCE_HOUSE_DEFAULTS, formatRelativeTime, thresholdOf, toMillis, formatFullTime, preferenceActionKey, DAY, HOUR, MINUTE } from './chunk-EKBWWA6P.js';
|
|
18
|
+
export { Button, ButtonSizeContext, ControlSizeContext, PreferencesContext, Spinner, formatFullTime, formatRelativeTime, preferenceActionKey, usePreferences } from './chunk-EKBWWA6P.js';
|
|
19
|
+
import { elementType, formatLocale, localeChoice } from './chunk-OYNUU346.js';
|
|
11
20
|
import { useBreakpoint, readBreakpointPx } from './chunk-CRQ6KCRD.js';
|
|
12
21
|
export { BreakpointWidthProvider, useBreakpoint } from './chunk-CRQ6KCRD.js';
|
|
13
22
|
import { FormChangeCtx, useReportedChange, useOptionalFormContext, FormCtx } from './chunk-XVB55M3N.js';
|
|
14
23
|
export { useFormContext } from './chunk-XVB55M3N.js';
|
|
15
|
-
import { Avatar, foldForSearch, useActiveOptionInView, shownMentions, matchMentions, mentionOptionId, MentionList, initialsOf } from './chunk-RWKCAKN3.js';
|
|
16
|
-
export { Avatar } from './chunk-RWKCAKN3.js';
|
|
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
24
|
import { CardSurfaceCtx, useScrollsInside, SplitPaneCtx, RowsCtx, PageActionsCtx, SurfaceBoundary, useFramesItself, TableCardCtx } from './chunk-QM4SJKWV.js';
|
|
21
25
|
import { FOCUSABLE, usePopupFocus, FIELD, ZOOM_KEYS, useOverlayLayer, useFocusTrap, useFocusBeforeOpen, rememberFocus, focusInitial, OVERLAY_CLOSE_ATTR, rovingTabStop, useGridKeyboard, focusAfterRemoval, useNonModalDialog, useReturnFocus } from './chunk-ZI3OQDET.js';
|
|
22
26
|
export { useGridKeyboard } from './chunk-ZI3OQDET.js';
|
|
23
|
-
import { Badge } from './chunk-EX64MN2U.js';
|
|
24
|
-
export { Badge } from './chunk-EX64MN2U.js';
|
|
25
27
|
import { useTextOverflow, Tooltip } from './chunk-MD2EFMES.js';
|
|
26
28
|
export { Tooltip, useTextOverflow } from './chunk-MD2EFMES.js';
|
|
27
29
|
import { mergeRefs, Slot } from './chunk-7Q46JXSK.js';
|
|
28
|
-
import { Icon, slotIcon, warnOnce } from './chunk-
|
|
30
|
+
import { Icon, slotIcon, warnOnce } from './chunk-TJEV7YAY.js';
|
|
29
31
|
import { usePosition } from './chunk-HP7WUZPK.js';
|
|
30
32
|
import { useLatest } from './chunk-WH2FUFAC.js';
|
|
31
33
|
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';
|
|
@@ -459,6 +461,27 @@ function Combobox({ value, onChange: onChangeProp, options, placeholder = "Searc
|
|
|
459
461
|
] });
|
|
460
462
|
return /* @__PURE__ */ jsx(Tooltip, { content: selectedLabel, disabled: !labelTruncated || open, children: triggerContent });
|
|
461
463
|
}
|
|
464
|
+
|
|
465
|
+
// ../../showcase/src/lib/locale-cache.ts
|
|
466
|
+
var caches = /* @__PURE__ */ new Set();
|
|
467
|
+
function localeCache(limit) {
|
|
468
|
+
const map = /* @__PURE__ */ new Map();
|
|
469
|
+
caches.add(map);
|
|
470
|
+
return (key, make) => {
|
|
471
|
+
const hit = map.get(key);
|
|
472
|
+
if (hit !== void 0) {
|
|
473
|
+
map.delete(key);
|
|
474
|
+
map.set(key, hit);
|
|
475
|
+
return hit;
|
|
476
|
+
}
|
|
477
|
+
const made = make();
|
|
478
|
+
map.set(key, made);
|
|
479
|
+
if (map.size > limit) map.delete(map.keys().next().value);
|
|
480
|
+
return made;
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// ../../showcase/src/lib/time-zones.ts
|
|
462
485
|
function canonicalTimeZone(zone) {
|
|
463
486
|
try {
|
|
464
487
|
return new Intl.DateTimeFormat("en-US", { timeZone: zone }).resolvedOptions().timeZone;
|
|
@@ -473,9 +496,9 @@ function browserTimeZone() {
|
|
|
473
496
|
return "UTC";
|
|
474
497
|
}
|
|
475
498
|
}
|
|
476
|
-
function timeZoneOffset(zone, at = /* @__PURE__ */ new Date()) {
|
|
499
|
+
function timeZoneOffset(zone, at = /* @__PURE__ */ new Date(), locale = formatLocale()) {
|
|
477
500
|
try {
|
|
478
|
-
return new Intl.DateTimeFormat(
|
|
501
|
+
return new Intl.DateTimeFormat(locale, { timeZone: zone, timeZoneName: "shortOffset" }).formatToParts(at).find((p) => p.type === "timeZoneName")?.value ?? "";
|
|
479
502
|
} catch {
|
|
480
503
|
return "";
|
|
481
504
|
}
|
|
@@ -485,6 +508,9 @@ function timeZones() {
|
|
|
485
508
|
const zones = [...new Set(listed.map(canonicalTimeZone))].filter((z) => z !== "UTC").sort((a, b) => a.localeCompare(b));
|
|
486
509
|
return ["UTC", ...zones];
|
|
487
510
|
}
|
|
511
|
+
function useBrowserTimeZone() {
|
|
512
|
+
return useHydrated() ? browserTimeZone() : void 0;
|
|
513
|
+
}
|
|
488
514
|
var RENAMED_CITIES = [
|
|
489
515
|
["Kolkata", ["Asia/Calcutta", "Asia/Kolkata"]],
|
|
490
516
|
["Kyiv", ["Europe/Kiev", "Europe/Kyiv"]],
|
|
@@ -503,81 +529,47 @@ var RENAMED_CITIES = [
|
|
|
503
529
|
["Ulaanbaatar", ["Asia/Ulan_Bator", "Asia/Ulaanbaatar"]]
|
|
504
530
|
];
|
|
505
531
|
var CITY_OF = new Map(RENAMED_CITIES.flatMap(([city, zones]) => zones.map((zone) => [zone, city])));
|
|
506
|
-
var labelOf = (zone, at) => {
|
|
507
|
-
const offset = timeZoneOffset(zone, at);
|
|
532
|
+
var labelOf = (zone, at, locale) => {
|
|
533
|
+
const offset = timeZoneOffset(zone, at, locale);
|
|
508
534
|
return offset ? `${zone.replace(/_/g, " ")} (${offset})` : zone.replace(/_/g, " ");
|
|
509
535
|
};
|
|
510
|
-
var
|
|
511
|
-
var
|
|
512
|
-
function zoneOptions() {
|
|
536
|
+
var HOUR2 = 36e5;
|
|
537
|
+
var zoneLists = localeCache(8);
|
|
538
|
+
function zoneOptions(locale) {
|
|
513
539
|
const now = Date.now();
|
|
514
|
-
|
|
540
|
+
const build2 = () => {
|
|
515
541
|
const at = new Date(now);
|
|
516
|
-
|
|
517
|
-
}
|
|
518
|
-
|
|
542
|
+
return { at: now, options: timeZones().map((zone) => ({ value: zone, label: labelOf(zone, at, locale), keywords: CITY_OF.get(zone) })) };
|
|
543
|
+
};
|
|
544
|
+
const key = `${locale ?? ""}|${Math.floor(now / HOUR2)}`;
|
|
545
|
+
return zoneLists(key, build2).options;
|
|
519
546
|
}
|
|
520
547
|
function TimezoneSelect({ value, onChange, placeholder = "Search time zones\u2026", ...rest }) {
|
|
521
|
-
const
|
|
548
|
+
const locale = useFormatLocale();
|
|
549
|
+
const zones = zoneOptions(locale);
|
|
522
550
|
const stored = value ? canonicalTimeZone(value) : "";
|
|
551
|
+
const mine = useBrowserTimeZone();
|
|
523
552
|
const options = useMemo(() => {
|
|
524
553
|
if (!stored) {
|
|
525
|
-
|
|
526
|
-
const label = zones.find((o) => o.value === mine)?.label ?? labelOf(mine, /* @__PURE__ */ new Date());
|
|
554
|
+
if (!mine) return zones;
|
|
555
|
+
const label = zones.find((o) => o.value === mine)?.label ?? labelOf(mine, /* @__PURE__ */ new Date(), locale);
|
|
527
556
|
return [{ value: mine, label: `${label} \xB7 your time zone`, keywords: CITY_OF.get(mine) }, ...zones.filter((o) => o.value !== mine)];
|
|
528
557
|
}
|
|
529
|
-
return zones.some((o) => o.value === stored) ? zones : [{ value: stored, label: labelOf(stored, /* @__PURE__ */ new Date()), keywords: CITY_OF.get(stored) }, ...zones];
|
|
530
|
-
}, [zones, stored]);
|
|
558
|
+
return zones.some((o) => o.value === stored) ? zones : [{ value: stored, label: labelOf(stored, /* @__PURE__ */ new Date(), locale), keywords: CITY_OF.get(stored) }, ...zones];
|
|
559
|
+
}, [zones, stored, mine, locale]);
|
|
531
560
|
return /* @__PURE__ */ jsx(Combobox, { value: stored, onChange, options, placeholder, ...rest });
|
|
532
561
|
}
|
|
533
|
-
var MINUTE = 6e4;
|
|
534
|
-
var HOUR2 = 60 * MINUTE;
|
|
535
|
-
var DAY = 24 * HOUR2;
|
|
536
562
|
var LONGEST_WAIT = DAY;
|
|
537
563
|
var CONTROL_ANCESTOR = 'a[href], button, summary, label, [role="button"], [role="link"], [role="option"], [role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"], [role="tab"], [role="treeitem"], [role="row"], [role="gridcell"], [role="checkbox"], [role="radio"], [role="switch"]';
|
|
538
564
|
var noChange = () => () => {
|
|
539
565
|
};
|
|
540
566
|
var inBrowser = () => true;
|
|
541
567
|
var onServer = () => false;
|
|
542
|
-
function toMillis(time) {
|
|
543
|
-
if (time instanceof Date) return time.getTime();
|
|
544
|
-
if (typeof time === "number") return time;
|
|
545
|
-
if (typeof time !== "string") return NaN;
|
|
546
|
-
const day = /^(\d{4})-(\d{2})-(\d{2})$/.exec(time.trim());
|
|
547
|
-
if (day) return new Date(Number(day[1]), Number(day[2]) - 1, Number(day[3])).getTime();
|
|
548
|
-
return Date.parse(time);
|
|
549
|
-
}
|
|
550
|
-
function thresholdOf(hours, from) {
|
|
551
|
-
if (typeof hours === "number" && Number.isFinite(hours) && hours >= 0) return hours;
|
|
552
|
-
const house = PREFERENCE_HOUSE_DEFAULTS.relativeThresholdHours;
|
|
553
|
-
warnOnce(from, `a threshold of ${String(hours)} isn't a number of hours, so the house's ${house} is used.`);
|
|
554
|
-
return house;
|
|
555
|
-
}
|
|
556
|
-
function midnight(t) {
|
|
557
|
-
const d = new Date(t);
|
|
558
|
-
d.setHours(0, 0, 0, 0);
|
|
559
|
-
return d.getTime();
|
|
560
|
-
}
|
|
561
|
-
function formatRelativeTime(time, options) {
|
|
562
|
-
const at = toMillis(time);
|
|
563
|
-
if (!Number.isFinite(at)) return "";
|
|
564
|
-
const now = options.now ?? Date.now();
|
|
565
|
-
const diff = at - now;
|
|
566
|
-
const age = Math.abs(diff);
|
|
567
|
-
if (age > thresholdOf(options.thresholdHours, "formatRelativeTime") * HOUR2) return new Intl.DateTimeFormat(formatLocale(), { dateStyle: "medium", timeStyle: "short" }).format(at);
|
|
568
|
-
const rtf = new Intl.RelativeTimeFormat(formatLocale(), { numeric: "auto" });
|
|
569
|
-
if (age < MINUTE) return rtf.format(0, "second");
|
|
570
|
-
if (age < HOUR2) return rtf.format(Math.trunc(diff / MINUTE), "minute");
|
|
571
|
-
if (age < DAY) return rtf.format(Math.trunc(diff / HOUR2), "hour");
|
|
572
|
-
return rtf.format(Math.round((midnight(at) - midnight(now)) / DAY), "day");
|
|
573
|
-
}
|
|
574
568
|
function useRelativeTimeFormat() {
|
|
575
569
|
const thresholdHours = useShellPreferences().relativeThresholdHours ?? PREFERENCE_HOUSE_DEFAULTS.relativeThresholdHours;
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
const at = toMillis(time);
|
|
580
|
-
return Number.isFinite(at) ? new Intl.DateTimeFormat(formatLocale(), { year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "2-digit", timeZoneName: "short" }).format(at) : "";
|
|
570
|
+
const locale = useFormatLocale();
|
|
571
|
+
const hydrated = useHydrated();
|
|
572
|
+
return useCallback((time) => hydrated ? formatRelativeTime(time, { thresholdHours, locale }) : "", [hydrated, thresholdHours, locale]);
|
|
581
573
|
}
|
|
582
574
|
function nextChange(at, now, threshold) {
|
|
583
575
|
const diff = at - now;
|
|
@@ -587,7 +579,7 @@ function nextChange(at, now, threshold) {
|
|
|
587
579
|
if (diff <= 0) return null;
|
|
588
580
|
wait = age - threshold + 1;
|
|
589
581
|
} else {
|
|
590
|
-
const step = age <
|
|
582
|
+
const step = age < HOUR ? MINUTE : HOUR;
|
|
591
583
|
const untilStep = diff > 0 ? age % step + 1 : step - age % step;
|
|
592
584
|
wait = diff > 0 ? untilStep : Math.min(untilStep, threshold - age + 1);
|
|
593
585
|
}
|
|
@@ -604,6 +596,7 @@ function RelativeTime({ time, thresholdHours, className }) {
|
|
|
604
596
|
return /* @__PURE__ */ jsx(RelativeTimeAt, { at, hours, className }, `${at}:${hours}`);
|
|
605
597
|
}
|
|
606
598
|
function RelativeTimeAt({ at, hours, className }) {
|
|
599
|
+
const locale = useFormatLocale();
|
|
607
600
|
const inRows = useContext(RowsCtx);
|
|
608
601
|
const [now, setNow] = useState(() => Date.now());
|
|
609
602
|
const [inControl, setInControl] = useState(false);
|
|
@@ -614,12 +607,12 @@ function RelativeTimeAt({ at, hours, className }) {
|
|
|
614
607
|
}, []);
|
|
615
608
|
const mounted = useSyncExternalStore(noChange, inBrowser, onServer);
|
|
616
609
|
useEffect(() => {
|
|
617
|
-
const wait = nextChange(at, now, hours *
|
|
610
|
+
const wait = nextChange(at, now, hours * HOUR);
|
|
618
611
|
if (wait === null) return;
|
|
619
612
|
const timer = setTimeout(() => setNow(Date.now()), wait);
|
|
620
613
|
return () => clearTimeout(timer);
|
|
621
614
|
}, [at, now, hours]);
|
|
622
|
-
const full = formatFullTime(at);
|
|
615
|
+
const full = formatFullTime(at, locale);
|
|
623
616
|
return /* @__PURE__ */ jsx(Tooltip, { content: full, ref: placed, children: /* @__PURE__ */ jsxs(
|
|
624
617
|
"time",
|
|
625
618
|
{
|
|
@@ -629,7 +622,7 @@ function RelativeTimeAt({ at, hours, className }) {
|
|
|
629
622
|
suppressHydrationWarning: true,
|
|
630
623
|
className: cn("rounded-[var(--ds-radius-sm)] focus-visible:outline-2 focus-visible:outline-[var(--ds-accent-primary)] focus-visible:outline-offset-2", className),
|
|
631
624
|
children: [
|
|
632
|
-
formatRelativeTime(at, { thresholdHours: hours, now }),
|
|
625
|
+
formatRelativeTime(at, { thresholdHours: hours, now, locale }),
|
|
633
626
|
/* @__PURE__ */ jsx("span", { className: "sr-only", suppressHydrationWarning: true, children: `, ${full}` })
|
|
634
627
|
]
|
|
635
628
|
},
|
|
@@ -751,6 +744,7 @@ function RadioGroup({ value, onChange: onChangeProp, options, orientation = "ver
|
|
|
751
744
|
const prev = isVertical ? "ArrowUp" : "ArrowLeft";
|
|
752
745
|
const next = isVertical ? "ArrowDown" : "ArrowRight";
|
|
753
746
|
if (e.key !== prev && e.key !== next) return;
|
|
747
|
+
if (e.target.getAttribute("role") !== "radio") return;
|
|
754
748
|
e.preventDefault();
|
|
755
749
|
const currentIdx = enabledOptions.findIndex((o) => o.value === value);
|
|
756
750
|
let nextIdx;
|
|
@@ -785,45 +779,48 @@ function RadioGroup({ value, onChange: onChangeProp, options, orientation = "ver
|
|
|
785
779
|
onKeyDown: handleKeyDown,
|
|
786
780
|
children: options.map((option, i) => {
|
|
787
781
|
const selected = option.value === value;
|
|
788
|
-
return /* @__PURE__ */ jsxs(
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
children: [
|
|
806
|
-
/* @__PURE__ */ jsx(
|
|
807
|
-
"span",
|
|
808
|
-
{
|
|
809
|
-
className: cn(
|
|
810
|
-
"flex items-center justify-center",
|
|
811
|
-
"h-[18px] w-[18px] shrink-0 rounded-[var(--ds-radius-full)]",
|
|
812
|
-
"border-[length:var(--ds-border-width)] border-[var(--ds-input-border)]",
|
|
813
|
-
"bg-[var(--ds-input-bg)]",
|
|
814
|
-
"transition-colors",
|
|
815
|
-
selected && "border-[var(--ds-check-border)]",
|
|
816
|
-
"group-focus-visible:shadow-[var(--ds-shadow-focus)]"
|
|
817
|
-
),
|
|
818
|
-
children: selected && // Sprint 25.14 A20: the checked colour, as a checkbox's fill (a preset whose accent falls short of 3:1 sets it)
|
|
819
|
-
/* @__PURE__ */ jsx("span", { className: cn("h-2.5 w-2.5 rounded-[var(--ds-radius-full)]", CHECK_FILL) })
|
|
820
|
-
}
|
|
782
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
783
|
+
/* @__PURE__ */ jsxs(
|
|
784
|
+
"button",
|
|
785
|
+
{
|
|
786
|
+
role: "radio",
|
|
787
|
+
type: "button",
|
|
788
|
+
"aria-checked": selected,
|
|
789
|
+
"aria-disabled": option.disabled || void 0,
|
|
790
|
+
"data-value": option.value,
|
|
791
|
+
tabIndex: i === tabStop ? 0 : -1,
|
|
792
|
+
disabled: option.disabled,
|
|
793
|
+
onClick: () => {
|
|
794
|
+
if (!option.disabled) onChange(option.value);
|
|
795
|
+
},
|
|
796
|
+
className: cn(
|
|
797
|
+
"group inline-flex items-center gap-ds-2 cursor-pointer select-none text-left outline-none",
|
|
798
|
+
option.disabled && "opacity-disabled cursor-not-allowed"
|
|
821
799
|
),
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
800
|
+
children: [
|
|
801
|
+
/* @__PURE__ */ jsx(
|
|
802
|
+
"span",
|
|
803
|
+
{
|
|
804
|
+
className: cn(
|
|
805
|
+
"flex items-center justify-center",
|
|
806
|
+
"h-[18px] w-[18px] shrink-0 rounded-[var(--ds-radius-full)]",
|
|
807
|
+
"border-[length:var(--ds-border-width)] border-[var(--ds-input-border)]",
|
|
808
|
+
"bg-[var(--ds-input-bg)]",
|
|
809
|
+
"transition-colors",
|
|
810
|
+
selected && "border-[var(--ds-check-border)]",
|
|
811
|
+
"group-focus-visible:shadow-[var(--ds-shadow-focus)]"
|
|
812
|
+
),
|
|
813
|
+
children: selected && // Sprint 25.14 A20: the checked colour, as a checkbox's fill (a preset whose accent falls short of 3:1 sets it)
|
|
814
|
+
/* @__PURE__ */ jsx("span", { className: cn("h-2.5 w-2.5 rounded-[var(--ds-radius-full)]", CHECK_FILL) })
|
|
815
|
+
}
|
|
816
|
+
),
|
|
817
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-[var(--ds-text-primary)]", children: option.label })
|
|
818
|
+
]
|
|
819
|
+
}
|
|
820
|
+
),
|
|
821
|
+
selected && option.reveal != null && // under the option, lined up with its label (the 18 px radio and its gap), a rule on its left tying it to it
|
|
822
|
+
/* @__PURE__ */ jsx("div", { "data-radio-reveal": "", className: "ml-[9px] pl-[calc(9px+var(--ds-space-2))] border-l-[length:var(--ds-border-width)] border-[var(--ds-border-default)] py-ds-1", children: option.reveal })
|
|
823
|
+
] }, option.value);
|
|
827
824
|
})
|
|
828
825
|
}
|
|
829
826
|
)
|
|
@@ -836,8 +833,8 @@ function addDays(d, n) {
|
|
|
836
833
|
}
|
|
837
834
|
function addMonthsClamped(d, n) {
|
|
838
835
|
const first = new Date(d.getFullYear(), d.getMonth() + n, 1);
|
|
839
|
-
const
|
|
840
|
-
return new Date(first.getFullYear(), first.getMonth(), Math.min(d.getDate(),
|
|
836
|
+
const last2 = new Date(first.getFullYear(), first.getMonth() + 1, 0).getDate();
|
|
837
|
+
return new Date(first.getFullYear(), first.getMonth(), Math.min(d.getDate(), last2));
|
|
841
838
|
}
|
|
842
839
|
function dayKey(d) {
|
|
843
840
|
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
@@ -895,25 +892,55 @@ function dateSegments(dayFirst, daysInMonth = 31) {
|
|
|
895
892
|
const year = { key: "year", label: "Year", min: 1, max: 9999, maxDigits: 4, placeholder: "yyyy" };
|
|
896
893
|
return dayFirst ? [day, month, year] : [month, day, year];
|
|
897
894
|
}
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
895
|
+
var FIRST_DAY_BY_REGION = Object.fromEntries([
|
|
896
|
+
...["AG", "AS", "BD", "BR", "BS", "BT", "BW", "BZ", "CA", "CO", "DM", "DO", "ET", "GT", "GU", "HK", "HN", "ID", "IL", "IN", "JM", "JP", "KE", "KH", "KR", "LA", "MH", "MM", "MO", "MT", "MX", "MZ", "NI", "NP", "PA", "PE", "PH", "PK", "PR", "PT", "PY", "SA", "SG", "SV", "TH", "TT", "TW", "UM", "US", "VE", "VI", "WS", "YE", "ZA", "ZW"].map((r) => [r, 0]),
|
|
897
|
+
...["AF", "BH", "DJ", "DZ", "EG", "IQ", "IR", "JO", "KW", "LY", "OM", "QA", "SD", "SY"].map((r) => [r, 6]),
|
|
898
|
+
["MV", 5]
|
|
899
|
+
]);
|
|
900
|
+
function weekStartOf(tag) {
|
|
901
|
+
if (!tag) return void 0;
|
|
902
|
+
try {
|
|
903
|
+
const locale = new Intl.Locale(tag);
|
|
904
|
+
const info = typeof locale.getWeekInfo === "function" ? locale.getWeekInfo() : locale.weekInfo;
|
|
905
|
+
if (info && typeof info.firstDay === "number" && info.firstDay >= 1 && info.firstDay <= 7) return info.firstDay % 7;
|
|
906
|
+
const region = locale.region ?? locale.maximize().region;
|
|
907
|
+
if (!region) return void 0;
|
|
908
|
+
return FIRST_DAY_BY_REGION[region] ?? 1;
|
|
909
|
+
} catch {
|
|
910
|
+
return void 0;
|
|
908
911
|
}
|
|
909
|
-
return f;
|
|
910
912
|
}
|
|
911
|
-
|
|
912
|
-
|
|
913
|
+
var last = null;
|
|
914
|
+
function firstDayFor(spoken, page) {
|
|
915
|
+
for (const tag of [...spoken, page]) {
|
|
916
|
+
const found = weekStartOf(tag);
|
|
917
|
+
if (found !== void 0) return found;
|
|
918
|
+
}
|
|
919
|
+
return 1;
|
|
920
|
+
}
|
|
921
|
+
function regionWeekStart() {
|
|
922
|
+
if (typeof document === "undefined") return 1;
|
|
923
|
+
const spoken = typeof navigator === "undefined" ? [] : navigator.languages?.length ? navigator.languages : navigator.language ? [navigator.language] : [];
|
|
924
|
+
const page = formatLocale();
|
|
925
|
+
const key = `${spoken.join(",")}|${page ?? ""}`;
|
|
926
|
+
if (last?.key === key) return last.day;
|
|
927
|
+
const day = firstDayFor(spoken, page);
|
|
928
|
+
last = { key, day };
|
|
929
|
+
return day;
|
|
930
|
+
}
|
|
931
|
+
function useWeekStart(own, locale) {
|
|
932
|
+
const readable = useHydrated();
|
|
933
|
+
const choice = useContext(LocaleContext);
|
|
934
|
+
if (own !== void 0) return own;
|
|
935
|
+
if (locale !== void 0) return weekStartOf(locale) ?? 1;
|
|
936
|
+
if (readable) return regionWeekStart();
|
|
937
|
+
return choice?.hasHeader ? firstDayFor(choice.spoken, choice.server) : 1;
|
|
913
938
|
}
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
939
|
+
|
|
940
|
+
// ../../showcase/src/components/Calendar/calendar-utils.ts
|
|
941
|
+
var formatters = localeCache(512);
|
|
942
|
+
function dtfFor(locale, options) {
|
|
943
|
+
return formatters(`${locale ?? ""}|${JSON.stringify(options)}`, () => new Intl.DateTimeFormat(locale, options));
|
|
917
944
|
}
|
|
918
945
|
function isSameDay(a, b) {
|
|
919
946
|
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
@@ -921,9 +948,6 @@ function isSameDay(a, b) {
|
|
|
921
948
|
function isSameMonth(a, b) {
|
|
922
949
|
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();
|
|
923
950
|
}
|
|
924
|
-
function isToday(d) {
|
|
925
|
-
return isSameDay(d, /* @__PURE__ */ new Date());
|
|
926
|
-
}
|
|
927
951
|
function isWeekend(d) {
|
|
928
952
|
const day = d.getDay();
|
|
929
953
|
return day === 0 || day === 6;
|
|
@@ -989,8 +1013,8 @@ function eventSpan(e) {
|
|
|
989
1013
|
const first = startOfDay(e.start);
|
|
990
1014
|
if (!e.end) return { first, last: first };
|
|
991
1015
|
const lastInstant = e.allDay ? e.end : new Date(e.end.getTime() - 1);
|
|
992
|
-
const
|
|
993
|
-
return { first, last:
|
|
1016
|
+
const last2 = startOfDay(lastInstant);
|
|
1017
|
+
return { first, last: last2 < first ? first : last2 };
|
|
994
1018
|
}
|
|
995
1019
|
function isBarEvent(e) {
|
|
996
1020
|
if (e.allDay) return true;
|
|
@@ -1002,10 +1026,24 @@ function isBarEvent(e) {
|
|
|
1002
1026
|
function getEventsForDay(events, date) {
|
|
1003
1027
|
const day = startOfDay(date).getTime();
|
|
1004
1028
|
return events.filter((e) => {
|
|
1005
|
-
const { first, last } = eventSpan(e);
|
|
1006
|
-
return first.getTime() <= day && day <=
|
|
1029
|
+
const { first, last: last2 } = eventSpan(e);
|
|
1030
|
+
return first.getTime() <= day && day <= last2.getTime();
|
|
1007
1031
|
});
|
|
1008
1032
|
}
|
|
1033
|
+
function groupEventsByDay(events, from, to) {
|
|
1034
|
+
const out = /* @__PURE__ */ new Map();
|
|
1035
|
+
const lo = startOfDay(from), hi = startOfDay(to);
|
|
1036
|
+
for (const e of events) {
|
|
1037
|
+
const { first, last: last2 } = eventSpan(e);
|
|
1038
|
+
for (let day = first < lo ? lo : first; day <= last2 && day < hi; day = new Date(day.getFullYear(), day.getMonth(), day.getDate() + 1)) {
|
|
1039
|
+
const key = dayKey(day);
|
|
1040
|
+
const list2 = out.get(key);
|
|
1041
|
+
if (list2) list2.push(e);
|
|
1042
|
+
else out.set(key, [e]);
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
return out;
|
|
1046
|
+
}
|
|
1009
1047
|
function dayPieces(events, date) {
|
|
1010
1048
|
const dayStart = startOfDay(date);
|
|
1011
1049
|
const next = new Date(dayStart.getFullYear(), dayStart.getMonth(), dayStart.getDate() + 1);
|
|
@@ -1020,86 +1058,100 @@ function dayPieces(events, date) {
|
|
|
1020
1058
|
}
|
|
1021
1059
|
return pieces.sort((a, b) => a.start.getTime() - b.start.getTime() || b.end.getTime() - a.end.getTime());
|
|
1022
1060
|
}
|
|
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
1061
|
function endDays(start, end) {
|
|
1046
1062
|
return end > start ? daysBetween(start, new Date(end.getTime() - 1)) : daysBetween(start, end);
|
|
1047
1063
|
}
|
|
1048
|
-
function
|
|
1049
|
-
|
|
1050
|
-
const
|
|
1051
|
-
const
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
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);
|
|
1064
|
+
function makeDateWords(locale) {
|
|
1065
|
+
const dtf = (options) => dtfFor(locale, options);
|
|
1066
|
+
const twelveHour = () => /^h1[12]$/.test(dtf({ hour: "numeric" }).resolvedOptions().hourCycle ?? "");
|
|
1067
|
+
const timeOptions = () => ({ hour: twelveHour() ? "numeric" : "2-digit", minute: "2-digit" });
|
|
1068
|
+
const dayOffset = (days) => new Intl.NumberFormat(locale, { signDisplay: "always" }).format(days);
|
|
1069
|
+
function monthName2(month, width = "long") {
|
|
1070
|
+
return dtf({ month: width }).format(new Date(2026, month, 1));
|
|
1071
|
+
}
|
|
1072
|
+
function weekdayNames(weekStartsOn, width = "short") {
|
|
1073
|
+
const f = dtf({ weekday: width });
|
|
1074
|
+
return Array.from({ length: 7 }, (_, i) => f.format(new Date(2026, 0, 4 + weekStartsOn + i)));
|
|
1081
1075
|
}
|
|
1082
|
-
|
|
1083
|
-
|
|
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)}`;
|
|
1076
|
+
function formatTime2(d) {
|
|
1077
|
+
return dtf(timeOptions()).format(d);
|
|
1086
1078
|
}
|
|
1087
|
-
|
|
1079
|
+
function formatHourLabel(hour) {
|
|
1080
|
+
const at = new Date(2026, 0, 5, hour);
|
|
1081
|
+
return twelveHour() ? dtf({ hour: "numeric" }).format(at) : dtf({ hour: "2-digit", minute: "2-digit" }).format(at);
|
|
1082
|
+
}
|
|
1083
|
+
function formatTimeRange(start, end) {
|
|
1084
|
+
if (!end) return formatTime2(start);
|
|
1085
|
+
const f = dtf(timeOptions());
|
|
1086
|
+
if (daysBetween(start, end) === 0) return f.formatRange(start, end);
|
|
1087
|
+
const sep = f.formatRangeToParts(start, end).find((p) => p.source === "shared" && p.type === "literal")?.value ?? " \u2013 ";
|
|
1088
|
+
const days = endDays(start, end);
|
|
1089
|
+
return days === 0 ? `${f.format(start)}${sep}${f.format(end)}` : `${f.format(start)}${sep}${f.format(end)} (${dayOffset(days)})`;
|
|
1090
|
+
}
|
|
1091
|
+
function speakTimeRange(start, end) {
|
|
1092
|
+
if (!end) return formatTime2(start);
|
|
1093
|
+
const days = endDays(start, end);
|
|
1094
|
+
const to = `${formatTime2(start)} to ${formatTime2(end)}`;
|
|
1095
|
+
return days === 0 ? to : days === 1 ? `${to} the next day` : `${to}, ${days} days later`;
|
|
1096
|
+
}
|
|
1097
|
+
function formatMonthYear(d) {
|
|
1098
|
+
return dtf({ month: "long", year: "numeric" }).format(d);
|
|
1099
|
+
}
|
|
1100
|
+
function formatDayLong(d) {
|
|
1101
|
+
return dtf({ weekday: "long", day: "numeric", month: "long", year: "numeric" }).format(d);
|
|
1102
|
+
}
|
|
1103
|
+
function formatDayShort(d) {
|
|
1104
|
+
return dtf({ weekday: "short", day: "numeric", month: "short" }).format(d);
|
|
1105
|
+
}
|
|
1106
|
+
function formatDayMedium(d) {
|
|
1107
|
+
return dtf({ day: "numeric", month: "short", year: "numeric" }).format(d);
|
|
1108
|
+
}
|
|
1109
|
+
function formatDayRange(start, end) {
|
|
1110
|
+
return dtf({ day: "numeric", month: "short", year: "numeric" }).formatRange(startOfDay(start), startOfDay(end));
|
|
1111
|
+
}
|
|
1112
|
+
function formatMonthRange(start, end) {
|
|
1113
|
+
return dtf({ month: "long", year: "numeric" }).formatRange(new Date(start.getFullYear(), start.getMonth(), 1), new Date(end.getFullYear(), end.getMonth(), 1));
|
|
1114
|
+
}
|
|
1115
|
+
function formatWeekRange(d, weekStartsOn = 0) {
|
|
1116
|
+
return dtf({ day: "numeric", month: "short", year: "numeric" }).formatRange(startOfWeek(d, weekStartsOn), startOfDay(endOfWeek(d, weekStartsOn)));
|
|
1117
|
+
}
|
|
1118
|
+
function formatEventWhen(e, spoken = false) {
|
|
1119
|
+
const { first, last: last2 } = eventSpan(e);
|
|
1120
|
+
const multiDay = last2 > first;
|
|
1121
|
+
if (e.allDay) {
|
|
1122
|
+
if (!multiDay) return spoken ? formatDayLong(first) : formatDayShort(first);
|
|
1123
|
+
return dtf(spoken ? { weekday: "long", day: "numeric", month: "long" } : { day: "numeric", month: "short" }).formatRange(first, last2);
|
|
1124
|
+
}
|
|
1125
|
+
if (!e.end || !isBarEvent(e)) {
|
|
1126
|
+
const day = spoken ? formatDayLong(e.start) : formatDayShort(e.start);
|
|
1127
|
+
const end = e.end && e.end > e.start ? e.end : void 0;
|
|
1128
|
+
return `${day}, ${spoken ? speakTimeRange(e.start, end) : formatTimeRange(e.start, end)}`;
|
|
1129
|
+
}
|
|
1130
|
+
return dtf({ weekday: "short", day: "numeric", month: "short", hour: "numeric", minute: "2-digit" }).formatRange(e.start, e.end);
|
|
1131
|
+
}
|
|
1132
|
+
return { monthName: monthName2, weekdayNames, formatTime: formatTime2, formatHourLabel, formatTimeRange, speakTimeRange, formatMonthYear, formatDayLong, formatDayShort, formatDayMedium, formatDayRange, formatMonthRange, formatWeekRange, formatEventWhen };
|
|
1133
|
+
}
|
|
1134
|
+
var wordsByLocale = localeCache(32);
|
|
1135
|
+
function dateWords(locale) {
|
|
1136
|
+
return wordsByLocale(locale ?? "", () => makeDateWords(locale));
|
|
1137
|
+
}
|
|
1138
|
+
function useDateWords() {
|
|
1139
|
+
return dateWords(useFormatLocale());
|
|
1088
1140
|
}
|
|
1089
1141
|
function layoutWeek(events, days, capacity) {
|
|
1090
1142
|
const weekStart = startOfDay(days[0]);
|
|
1091
1143
|
const weekEnd = startOfDay(days[days.length - 1]);
|
|
1092
1144
|
const items = [];
|
|
1093
1145
|
for (const event of events) {
|
|
1094
|
-
const { first, last } = eventSpan(event);
|
|
1095
|
-
if (
|
|
1146
|
+
const { first, last: last2 } = eventSpan(event);
|
|
1147
|
+
if (last2 < weekStart || first > weekEnd) continue;
|
|
1096
1148
|
items.push({
|
|
1097
1149
|
event,
|
|
1098
1150
|
startCol: Math.max(0, daysBetween(weekStart, first)),
|
|
1099
|
-
endCol: Math.min(days.length - 1, daysBetween(weekStart,
|
|
1151
|
+
endCol: Math.min(days.length - 1, daysBetween(weekStart, last2)),
|
|
1100
1152
|
before: first < weekStart,
|
|
1101
|
-
after:
|
|
1102
|
-
length: daysBetween(first,
|
|
1153
|
+
after: last2 > weekEnd,
|
|
1154
|
+
length: daysBetween(first, last2) + 1
|
|
1103
1155
|
});
|
|
1104
1156
|
}
|
|
1105
1157
|
items.sort((a, b) => {
|
|
@@ -1195,48 +1247,50 @@ var ENGLISH_MONTHS = [
|
|
|
1195
1247
|
function getDaysInMonth(year, month) {
|
|
1196
1248
|
return new Date(year, month + 1, 0).getDate();
|
|
1197
1249
|
}
|
|
1198
|
-
function getFirstDayOfWeek(year, month) {
|
|
1199
|
-
return new Date(year, month, 1).getDay();
|
|
1250
|
+
function getFirstDayOfWeek(year, month, weekStartsOn) {
|
|
1251
|
+
return (new Date(year, month, 1).getDay() - weekStartsOn + 7) % 7;
|
|
1200
1252
|
}
|
|
1201
1253
|
function isSameDay2(a, b) {
|
|
1202
1254
|
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
1203
1255
|
}
|
|
1204
|
-
function localeDayFirst() {
|
|
1256
|
+
function localeDayFirst(locale = formatLocale()) {
|
|
1205
1257
|
try {
|
|
1206
|
-
const parts = new Intl.DateTimeFormat(
|
|
1258
|
+
const parts = new Intl.DateTimeFormat(locale).formatToParts(new Date(2e3, 11, 25));
|
|
1207
1259
|
return parts.findIndex((p) => p.type === "day") < parts.findIndex((p) => p.type === "month");
|
|
1208
1260
|
} catch {
|
|
1209
1261
|
return true;
|
|
1210
1262
|
}
|
|
1211
1263
|
}
|
|
1264
|
+
var NO_SEGMENTS = { day: null, month: null, year: null };
|
|
1212
1265
|
function validDate(year, monthIndex2, day) {
|
|
1213
1266
|
if (monthIndex2 < 0 || monthIndex2 > 11 || day < 1) return null;
|
|
1214
1267
|
const d = new Date(year, monthIndex2, day);
|
|
1215
1268
|
return d.getFullYear() === year && d.getMonth() === monthIndex2 && d.getDate() === day ? d : null;
|
|
1216
1269
|
}
|
|
1217
|
-
function monthIndex(name) {
|
|
1270
|
+
function monthIndex(name, locale) {
|
|
1218
1271
|
const typed = name.toLocaleLowerCase().replace(/\.$/, "");
|
|
1219
1272
|
const fold = (m) => m.toLocaleLowerCase().replace(/\.$/, "");
|
|
1220
|
-
const
|
|
1221
|
-
|
|
1222
|
-
|
|
1273
|
+
const { monthName: monthName2 } = dateWords(locale);
|
|
1274
|
+
const lists = [ENGLISH_MONTHS, Array.from({ length: 12 }, (_, i) => fold(monthName2(i, "long"))), Array.from({ length: 12 }, (_, i) => fold(monthName2(i, "short")))];
|
|
1275
|
+
for (const list2 of lists) {
|
|
1276
|
+
const i = list2.findIndex((m) => m.startsWith(typed) || typed.length >= 3 && typed.startsWith(m));
|
|
1223
1277
|
if (i >= 0) return i;
|
|
1224
1278
|
}
|
|
1225
1279
|
return -1;
|
|
1226
1280
|
}
|
|
1227
|
-
function parseTypedDate(text, dayFirst = localeDayFirst()) {
|
|
1281
|
+
function parseTypedDate(text, dayFirst = localeDayFirst(), locale = formatLocale()) {
|
|
1228
1282
|
const t = text.trim().replace(/\s+/g, " ");
|
|
1229
1283
|
if (!t) return null;
|
|
1230
1284
|
let m = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(t);
|
|
1231
1285
|
if (m) return validDate(Number(m[1]), Number(m[2]) - 1, Number(m[3]));
|
|
1232
1286
|
m = /^(\p{L}{3,})\.?\s+(\d{1,2}),?\s+(\d{4})$/u.exec(t);
|
|
1233
1287
|
if (m) {
|
|
1234
|
-
const mi = monthIndex(m[1]);
|
|
1288
|
+
const mi = monthIndex(m[1], locale);
|
|
1235
1289
|
return mi < 0 ? null : validDate(Number(m[3]), mi, Number(m[2]));
|
|
1236
1290
|
}
|
|
1237
1291
|
m = /^(\d{1,2})\.?\s+(\p{L}{3,})\.?,?\s+(\d{4})$/u.exec(t);
|
|
1238
1292
|
if (m) {
|
|
1239
|
-
const mi = monthIndex(m[2]);
|
|
1293
|
+
const mi = monthIndex(m[2], locale);
|
|
1240
1294
|
return mi < 0 ? null : validDate(Number(m[3]), mi, Number(m[1]));
|
|
1241
1295
|
}
|
|
1242
1296
|
m = /^(\d{1,2})[/.-](\d{1,2})[/.-](\d{2,4})$/.exec(t);
|
|
@@ -1248,7 +1302,12 @@ function parseTypedDate(text, dayFirst = localeDayFirst()) {
|
|
|
1248
1302
|
}
|
|
1249
1303
|
return null;
|
|
1250
1304
|
}
|
|
1251
|
-
function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date", disabled, className, ref, container, error = false, label, id, size: sizeProp, min, max, range: range2, ...wiring }) {
|
|
1305
|
+
function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date", disabled, className, ref, container, error = false, label, id, size: sizeProp, min, max, range: range2, weekStartsOn: weekStartsOnProp, ...wiring }) {
|
|
1306
|
+
const weekStartsOn = useWeekStart(weekStartsOnProp);
|
|
1307
|
+
const locale = useFormatLocale();
|
|
1308
|
+
const { formatDayLong, formatMonthYear, weekdayNames } = useDateWords();
|
|
1309
|
+
const hydrated = useHydrated();
|
|
1310
|
+
const today = useToday();
|
|
1252
1311
|
const onChange = useReportedChange(onChangeProp, value);
|
|
1253
1312
|
const contextSize = useContext(ControlSizeContext);
|
|
1254
1313
|
const size = sizeProp ?? contextSize ?? "md";
|
|
@@ -1266,8 +1325,7 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1266
1325
|
const year = viewDate.getFullYear();
|
|
1267
1326
|
const month = viewDate.getMonth();
|
|
1268
1327
|
const daysInMonth = getDaysInMonth(year, month);
|
|
1269
|
-
const firstDay = getFirstDayOfWeek(year, month);
|
|
1270
|
-
const today = useMemo(() => /* @__PURE__ */ new Date(), []);
|
|
1328
|
+
const firstDay = getFirstDayOfWeek(year, month, weekStartsOn);
|
|
1271
1329
|
const startOf = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
1272
1330
|
const isDisabledDay = (d) => !!min && d < startOf(min) || !!max && d > startOf(max);
|
|
1273
1331
|
const [focusDate, setFocusDate] = useState(() => startOf(value ?? range2?.start ?? range2?.end ?? /* @__PURE__ */ new Date()));
|
|
@@ -1275,7 +1333,7 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1275
1333
|
if (open !== prevOpen) {
|
|
1276
1334
|
setPrevOpen(open);
|
|
1277
1335
|
if (open) {
|
|
1278
|
-
const start = startOf(value ?? range2?.start ?? range2?.end ?? today);
|
|
1336
|
+
const start = startOf(value ?? range2?.start ?? range2?.end ?? today ?? /* @__PURE__ */ new Date());
|
|
1279
1337
|
setFocusDate(start);
|
|
1280
1338
|
setViewDate(new Date(start.getFullYear(), start.getMonth(), 1));
|
|
1281
1339
|
}
|
|
@@ -1289,7 +1347,7 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1289
1347
|
active: focusDate,
|
|
1290
1348
|
setActive: showDay,
|
|
1291
1349
|
keyOf: dayKey,
|
|
1292
|
-
move: (from, e) => moveDay(from, e.key, e.shiftKey,
|
|
1350
|
+
move: (from, e) => moveDay(from, e.key, e.shiftKey, weekStartsOn)
|
|
1293
1351
|
});
|
|
1294
1352
|
const prevMonth = () => {
|
|
1295
1353
|
setViewDate(new Date(year, month - 1, 1));
|
|
@@ -1311,7 +1369,7 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1311
1369
|
onChange(d);
|
|
1312
1370
|
setOpen(false);
|
|
1313
1371
|
};
|
|
1314
|
-
const dayFirst = useMemo(() => localeDayFirst(), []);
|
|
1372
|
+
const dayFirst = useMemo(() => localeDayFirst(locale), [locale]);
|
|
1315
1373
|
const [segs, setSegs] = useState(() => value ? { day: value.getDate(), month: value.getMonth() + 1, year: value.getFullYear() } : { day: null, month: null, year: null });
|
|
1316
1374
|
const [buffers, setBuffers] = useState({});
|
|
1317
1375
|
const lastCommitted = useRef(null);
|
|
@@ -1320,7 +1378,7 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1320
1378
|
setSegs(value ? { day: value.getDate(), month: value.getMonth() + 1, year: value.getFullYear() } : { day: null, month: null, year: null });
|
|
1321
1379
|
setBuffers({});
|
|
1322
1380
|
}, [value]);
|
|
1323
|
-
const specs = dateSegments(dayFirst, segs.month && segs.year ? getDaysInMonth(segs.year, segs.month - 1) : 31);
|
|
1381
|
+
const specs = dateSegments(dayFirst, hydrated && segs.month && segs.year ? getDaysInMonth(segs.year, segs.month - 1) : 31);
|
|
1324
1382
|
const segmentRefs = useRef([]);
|
|
1325
1383
|
const focusSegment = (i) => {
|
|
1326
1384
|
segmentRefs.current[Math.max(0, Math.min(specs.length - 1, i))]?.focus();
|
|
@@ -1360,15 +1418,15 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1360
1418
|
setViewDate(d);
|
|
1361
1419
|
}
|
|
1362
1420
|
};
|
|
1363
|
-
const setSegment = (key, v,
|
|
1421
|
+
const setSegment = (key, v, commit2 = true) => {
|
|
1364
1422
|
setSegs((cur) => {
|
|
1365
1423
|
const next = { ...cur, [key]: v };
|
|
1366
|
-
if (
|
|
1424
|
+
if (commit2) commitIfComplete(next);
|
|
1367
1425
|
return next;
|
|
1368
1426
|
});
|
|
1369
1427
|
};
|
|
1370
1428
|
const applyTyped = (text) => {
|
|
1371
|
-
const d = parseTypedDate(text, dayFirst);
|
|
1429
|
+
const d = parseTypedDate(text, dayFirst, locale);
|
|
1372
1430
|
if (!d) return;
|
|
1373
1431
|
const next = { day: d.getDate(), month: d.getMonth() + 1, year: d.getFullYear() };
|
|
1374
1432
|
setSegs(next);
|
|
@@ -1420,12 +1478,13 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1420
1478
|
if (r.advance) focusSegment(index + 1);
|
|
1421
1479
|
}
|
|
1422
1480
|
};
|
|
1481
|
+
const drawn = hydrated ? segs : NO_SEGMENTS;
|
|
1423
1482
|
const shown = (spec) => {
|
|
1424
1483
|
const k = spec.key;
|
|
1425
1484
|
const b = buffers[k];
|
|
1426
|
-
if (b &&
|
|
1427
|
-
if (
|
|
1428
|
-
return k === "year" ? String(
|
|
1485
|
+
if (b && drawn[k] === null) return b;
|
|
1486
|
+
if (drawn[k] === null) return spec.placeholder;
|
|
1487
|
+
return k === "year" ? String(drawn[k]) : pad2(drawn[k]);
|
|
1429
1488
|
};
|
|
1430
1489
|
const selectDay = (day) => {
|
|
1431
1490
|
const d = new Date(year, month, day);
|
|
@@ -1499,11 +1558,11 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1499
1558
|
"aria-label": spec.label,
|
|
1500
1559
|
"aria-valuemin": spec.min,
|
|
1501
1560
|
"aria-valuemax": spec.max,
|
|
1502
|
-
"aria-valuenow":
|
|
1503
|
-
"aria-valuetext":
|
|
1561
|
+
"aria-valuenow": drawn[k] ?? void 0,
|
|
1562
|
+
"aria-valuetext": drawn[k] === null ? "empty" : String(drawn[k]),
|
|
1504
1563
|
onKeyDown: (e) => onSegmentKeyDown(e, i, spec),
|
|
1505
1564
|
onClick: (e) => e.stopPropagation(),
|
|
1506
|
-
className: cn("rounded-[var(--ds-radius-sm)] px-[2px] outline-none focus:bg-[var(--ds-accent-subtle)] focus:text-[var(--ds-accent-primary)] cursor-text",
|
|
1565
|
+
className: cn("rounded-[var(--ds-radius-sm)] px-[2px] outline-none focus:bg-[var(--ds-accent-subtle)] focus:text-[var(--ds-accent-primary)] cursor-text", drawn[k] === null && !buffers[k] && "text-[var(--ds-text-muted)]"),
|
|
1507
1566
|
children: shown(spec)
|
|
1508
1567
|
}
|
|
1509
1568
|
)
|
|
@@ -1566,13 +1625,13 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1566
1625
|
className: "flex flex-col gap-ds-0.5 tabular-nums",
|
|
1567
1626
|
style: { padding: "var(--ds-space-2) var(--ds-space-3)" },
|
|
1568
1627
|
children: [
|
|
1569
|
-
/* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 gap-ds-0.5 mb-ds-0.5", children: weekdayNames(
|
|
1628
|
+
/* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 gap-ds-0.5 mb-ds-0.5", children: weekdayNames(weekStartsOn, "narrow").map((d, i) => /* @__PURE__ */ jsx("div", { role: "columnheader", "aria-label": weekdayNames(weekStartsOn, "long")[i], className: "text-center text-2xs font-medium text-[var(--ds-text-muted)] py-ds-1", children: d }, i)) }),
|
|
1570
1629
|
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) => {
|
|
1571
1630
|
if (day === null) return /* @__PURE__ */ jsx("div", { role: "gridcell" }, `empty-${i}`);
|
|
1572
1631
|
const dateObj = new Date(year, month, day);
|
|
1573
1632
|
const isSelected = !!value && isSameDay2(dateObj, value);
|
|
1574
1633
|
const isOtherEnd = !!otherEnd && isSameDay2(dateObj, otherEnd);
|
|
1575
|
-
const
|
|
1634
|
+
const isToday = today !== null && isSameDay2(dateObj, today);
|
|
1576
1635
|
const between = inBand(dateObj);
|
|
1577
1636
|
const dis = isDisabledDay(dateObj);
|
|
1578
1637
|
return /* @__PURE__ */ jsx(
|
|
@@ -1589,13 +1648,13 @@ function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date"
|
|
|
1589
1648
|
},
|
|
1590
1649
|
onMouseEnter: () => setHover(dateObj),
|
|
1591
1650
|
"aria-selected": isSelected,
|
|
1592
|
-
"aria-current":
|
|
1651
|
+
"aria-current": isToday ? "date" : void 0,
|
|
1593
1652
|
"aria-label": formatDayLong(dateObj),
|
|
1594
1653
|
className: cn(
|
|
1595
1654
|
"w-full aspect-square flex items-center justify-center text-xs",
|
|
1596
1655
|
"transition-colors cursor-pointer",
|
|
1597
1656
|
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
1598
|
-
isSelected ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)] font-bold rounded-[var(--ds-radius-sm)]" : isOtherEnd ? "bg-[var(--ds-accent-muted)] text-[var(--ds-accent-subtle-text)] font-semibold rounded-[var(--ds-radius-sm)]" : between ? "bg-[var(--ds-accent-subtle)] text-[var(--ds-accent-subtle-text)] rounded-none" :
|
|
1657
|
+
isSelected ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)] font-bold rounded-[var(--ds-radius-sm)]" : isOtherEnd ? "bg-[var(--ds-accent-muted)] text-[var(--ds-accent-subtle-text)] font-semibold rounded-[var(--ds-radius-sm)]" : between ? "bg-[var(--ds-accent-subtle)] text-[var(--ds-accent-subtle-text)] rounded-none" : isToday ? "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)]",
|
|
1599
1658
|
dis && "opacity-disabled cursor-not-allowed hover:bg-transparent"
|
|
1600
1659
|
),
|
|
1601
1660
|
children: day
|
|
@@ -1692,10 +1751,14 @@ function DateRangePicker({
|
|
|
1692
1751
|
min,
|
|
1693
1752
|
max,
|
|
1694
1753
|
presets = DEFAULT_DATE_RANGE_PRESETS,
|
|
1695
|
-
weekStartsOn
|
|
1754
|
+
weekStartsOn: weekStartsOnProp,
|
|
1696
1755
|
size: sizeProp,
|
|
1697
1756
|
...wiring
|
|
1698
1757
|
}) {
|
|
1758
|
+
const weekStartsOn = useWeekStart(weekStartsOnProp);
|
|
1759
|
+
const { weekdayNames, formatDayLong, formatDayMedium, formatDayRange, formatMonthRange, formatMonthYear } = useDateWords();
|
|
1760
|
+
const hydrated = useHydrated();
|
|
1761
|
+
const now = useToday();
|
|
1699
1762
|
const onChange = useReportedChange(onChangeProp, value);
|
|
1700
1763
|
const contextSize = useContext(ControlSizeContext);
|
|
1701
1764
|
const size = sizeProp ?? contextSize ?? "md";
|
|
@@ -1709,7 +1772,7 @@ function DateRangePicker({
|
|
|
1709
1772
|
const triggerId = control.id ?? generatedId;
|
|
1710
1773
|
const labelledBy = control.labelId ? `${control.labelId} ${triggerId}` : void 0;
|
|
1711
1774
|
const pos = usePosition(triggerRef, panelRef, open, { side: "bottom", align: "start", offset: 4, flip: true });
|
|
1712
|
-
const today =
|
|
1775
|
+
const today = now && startOfDay(now);
|
|
1713
1776
|
const dayNames = weekdayNames(weekStartsOn, "narrow");
|
|
1714
1777
|
const dayNamesLong = weekdayNames(weekStartsOn, "long");
|
|
1715
1778
|
const gridRef = useRef(null);
|
|
@@ -1718,7 +1781,7 @@ function DateRangePicker({
|
|
|
1718
1781
|
if (open !== prevOpen) {
|
|
1719
1782
|
setPrevOpen(open);
|
|
1720
1783
|
if (open) {
|
|
1721
|
-
const start = startOfDay(value.start ?? today);
|
|
1784
|
+
const start = startOfDay(value.start ?? today ?? /* @__PURE__ */ new Date());
|
|
1722
1785
|
setFocusDate(start);
|
|
1723
1786
|
setViewDate(new Date(start.getFullYear(), start.getMonth(), 1));
|
|
1724
1787
|
}
|
|
@@ -1788,7 +1851,8 @@ function DateRangePicker({
|
|
|
1788
1851
|
const rangeEnd2 = value.end ?? previewEnd;
|
|
1789
1852
|
const inRange = (d) => !!(rangeStart && rangeEnd2 && d > rangeStart && d < rangeEnd2);
|
|
1790
1853
|
const months = [viewDate, addMonths(viewDate, 1)];
|
|
1791
|
-
const summary = value.start && value.end ? formatDayRange(value.start, value.end) : value.start ? `${formatDayMedium(value.start)} \u2013 \u2026` : null;
|
|
1854
|
+
const summary = !hydrated ? null : value.start && value.end ? formatDayRange(value.start, value.end) : value.start ? `${formatDayMedium(value.start)} \u2013 \u2026` : null;
|
|
1855
|
+
const pendingValue = !hydrated && !!value.start;
|
|
1792
1856
|
return /* @__PURE__ */ jsxs("div", { ref, className: cn(className), children: [
|
|
1793
1857
|
label && /* @__PURE__ */ jsx("label", { htmlFor: triggerId, className: "block text-sm font-medium text-[var(--ds-text-primary)] mb-ds-1", children: label }),
|
|
1794
1858
|
control.requiredNote,
|
|
@@ -1823,92 +1887,1066 @@ function DateRangePicker({
|
|
|
1823
1887
|
),
|
|
1824
1888
|
children: [
|
|
1825
1889
|
/* @__PURE__ */ jsx(Icon, { name: "calendar", size: 14, className: "text-[var(--ds-text-muted)]" }),
|
|
1826
|
-
/* @__PURE__ */ jsx("span", { className: "truncate", children: summary ?? placeholder })
|
|
1890
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: summary ?? (pendingValue ? "" : placeholder) })
|
|
1891
|
+
]
|
|
1892
|
+
}
|
|
1893
|
+
),
|
|
1894
|
+
open && createPortal(
|
|
1895
|
+
/* @__PURE__ */ jsxs(
|
|
1896
|
+
"div",
|
|
1897
|
+
{
|
|
1898
|
+
ref: panelRef,
|
|
1899
|
+
role: "dialog",
|
|
1900
|
+
"aria-label": "Choose a date range",
|
|
1901
|
+
tabIndex: -1,
|
|
1902
|
+
className: cn(
|
|
1903
|
+
"fixed z-[var(--ds-z-popover)] flex outline-none",
|
|
1904
|
+
"bg-[var(--ds-bg-surface-elevated)]",
|
|
1905
|
+
"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]",
|
|
1906
|
+
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
1907
|
+
"rounded-[var(--ds-radius-md)]",
|
|
1908
|
+
"shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]"
|
|
1909
|
+
),
|
|
1910
|
+
style: { top: pos.top, left: pos.left },
|
|
1911
|
+
children: [
|
|
1912
|
+
presets.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-ds-0.5 p-ds-2 border-r-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] min-w-[140px]", children: presets.map((p) => /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "justify-start", onClick: () => {
|
|
1913
|
+
const r = p.range();
|
|
1914
|
+
returnFocus();
|
|
1915
|
+
onChange(r);
|
|
1916
|
+
setViewDate(r.start ?? /* @__PURE__ */ new Date());
|
|
1917
|
+
setOpen(false);
|
|
1918
|
+
}, children: p.label }, p.label)) }),
|
|
1919
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
1920
|
+
/* @__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: [
|
|
1921
|
+
/* @__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" }) }),
|
|
1922
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-[var(--ds-text-primary)]", children: formatMonthRange(months[0], months[1]) }),
|
|
1923
|
+
/* @__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 }) })
|
|
1924
|
+
] }),
|
|
1925
|
+
/* @__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: [
|
|
1926
|
+
/* @__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)) }),
|
|
1927
|
+
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) => {
|
|
1928
|
+
if (!isSameMonth(d, m)) return /* @__PURE__ */ jsx("div", { role: "gridcell" }, d.toISOString());
|
|
1929
|
+
const isStart = !!rangeStart && isSameDay(d, rangeStart);
|
|
1930
|
+
const isEnd = !!rangeEnd2 && isSameDay(d, rangeEnd2);
|
|
1931
|
+
const between = inRange(d);
|
|
1932
|
+
const dis = isDisabledDay(d);
|
|
1933
|
+
return /* @__PURE__ */ jsx(
|
|
1934
|
+
"button",
|
|
1935
|
+
{
|
|
1936
|
+
type: "button",
|
|
1937
|
+
role: "gridcell",
|
|
1938
|
+
"data-grid-key": dayKey(d),
|
|
1939
|
+
tabIndex: grid.tabIndexOf(d),
|
|
1940
|
+
"aria-disabled": dis || void 0,
|
|
1941
|
+
onClick: () => selectDay(d),
|
|
1942
|
+
onFocus: () => {
|
|
1943
|
+
if (!isSameDay(d, focusDate)) setFocusDate(d);
|
|
1944
|
+
},
|
|
1945
|
+
onMouseEnter: () => setHover(d),
|
|
1946
|
+
"aria-selected": isStart || isEnd || between,
|
|
1947
|
+
"aria-current": today !== null && isSameDay(d, today) ? "date" : void 0,
|
|
1948
|
+
"aria-label": formatDayLong(d),
|
|
1949
|
+
className: cn(
|
|
1950
|
+
"w-full aspect-square flex items-center justify-center text-xs",
|
|
1951
|
+
"transition-colors cursor-pointer",
|
|
1952
|
+
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
1953
|
+
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" : today !== null && 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)]",
|
|
1954
|
+
dis && "opacity-disabled cursor-not-allowed hover:bg-transparent"
|
|
1955
|
+
),
|
|
1956
|
+
children: d.getDate()
|
|
1957
|
+
},
|
|
1958
|
+
d.toISOString()
|
|
1959
|
+
);
|
|
1960
|
+
}) }, w))
|
|
1961
|
+
] }, `${m.getFullYear()}-${m.getMonth()}`)) }),
|
|
1962
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center bg-[var(--ds-bg-muted)] border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] rounded-br-[var(--ds-radius-md)] px-ds-3 py-ds-2", children: [
|
|
1963
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--ds-text-muted)]", children: value.start && !value.end ? "Now pick an end date" : summary ?? "Pick a start date" }),
|
|
1964
|
+
(value.start || value.end) && /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => {
|
|
1965
|
+
onChange({ start: null, end: null });
|
|
1966
|
+
setHover(null);
|
|
1967
|
+
}, children: "Clear" })
|
|
1968
|
+
] })
|
|
1969
|
+
] })
|
|
1970
|
+
]
|
|
1971
|
+
}
|
|
1972
|
+
),
|
|
1973
|
+
container ?? document.body
|
|
1974
|
+
)
|
|
1975
|
+
] });
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1978
|
+
// ../../showcase/src/lib/recurrence.ts
|
|
1979
|
+
var DAY_CODES = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"];
|
|
1980
|
+
var FREQS = { DAILY: "daily", WEEKLY: "weekly", MONTHLY: "monthly", YEARLY: "yearly" };
|
|
1981
|
+
var KNOWN_PARTS = /* @__PURE__ */ new Set(["FREQ", "INTERVAL", "WKST", "BYDAY", "BYSETPOS", "BYMONTHDAY", "BYMONTH", "UNTIL", "COUNT"]);
|
|
1982
|
+
var whole = (text) => text !== void 0 && /^[+-]?\d+$/.test(text) ? Number(text) : null;
|
|
1983
|
+
function plainDays(text) {
|
|
1984
|
+
const days = text.split(",").map((code) => DAY_CODES.indexOf(code));
|
|
1985
|
+
if (days.some((d) => d < 0) || new Set(days).size !== days.length) return null;
|
|
1986
|
+
return days.sort((a, b) => a - b);
|
|
1987
|
+
}
|
|
1988
|
+
function nthDay(byday, setpos) {
|
|
1989
|
+
const m = /^([+-]?\d)?(SU|MO|TU|WE|TH|FR|SA)$/.exec(byday);
|
|
1990
|
+
if (!m) return null;
|
|
1991
|
+
const week = m[1] !== void 0 ? setpos === void 0 ? Number(m[1]) : NaN : whole(setpos);
|
|
1992
|
+
if (week === null || ![1, 2, 3, 4, -1].includes(week)) return null;
|
|
1993
|
+
return { week, weekday: DAY_CODES.indexOf(m[2]) };
|
|
1994
|
+
}
|
|
1995
|
+
function parseUntil(text) {
|
|
1996
|
+
const m = /^(\d{4})(\d{2})(\d{2})(?:T(\d{2})(\d{2})(\d{2})(Z)?)?$/.exec(text);
|
|
1997
|
+
if (!m) return null;
|
|
1998
|
+
const [y, mo, d] = [Number(m[1]), Number(m[2]) - 1, Number(m[3])];
|
|
1999
|
+
const date = m[4] === void 0 ? new Date(y, mo, d) : m[7] ? new Date(Date.UTC(y, mo, d, Number(m[4]), Number(m[5]), Number(m[6]))) : new Date(y, mo, d, Number(m[4]), Number(m[5]), Number(m[6]));
|
|
2000
|
+
return Number.isNaN(date.getTime()) || (m[7] ? date.getUTCMonth() : date.getMonth()) !== mo ? null : date;
|
|
2001
|
+
}
|
|
2002
|
+
function parseRRule(text) {
|
|
2003
|
+
if (typeof text !== "string") return null;
|
|
2004
|
+
const body = text.trim().replace(/^RRULE:/i, "");
|
|
2005
|
+
if (!body) return null;
|
|
2006
|
+
const parts = /* @__PURE__ */ new Map();
|
|
2007
|
+
for (const part of body.split(";")) {
|
|
2008
|
+
if (!part) continue;
|
|
2009
|
+
const at = part.indexOf("=");
|
|
2010
|
+
const key = part.slice(0, at).toUpperCase();
|
|
2011
|
+
if (at <= 0 || parts.has(key) || !KNOWN_PARTS.has(key)) return null;
|
|
2012
|
+
parts.set(key, part.slice(at + 1).toUpperCase());
|
|
2013
|
+
}
|
|
2014
|
+
const freq = FREQS[parts.get("FREQ") ?? ""];
|
|
2015
|
+
if (!freq) return null;
|
|
2016
|
+
const rule = { freq };
|
|
2017
|
+
if (parts.has("INTERVAL")) {
|
|
2018
|
+
const n = whole(parts.get("INTERVAL"));
|
|
2019
|
+
if (n === null || n < 1) return null;
|
|
2020
|
+
if (n > 1) rule.interval = n;
|
|
2021
|
+
}
|
|
2022
|
+
if (parts.has("WKST")) {
|
|
2023
|
+
const d = DAY_CODES.indexOf(parts.get("WKST"));
|
|
2024
|
+
if (d < 0) return null;
|
|
2025
|
+
if (d !== 1) rule.weekStart = d;
|
|
2026
|
+
}
|
|
2027
|
+
if (parts.has("UNTIL") && parts.has("COUNT")) return null;
|
|
2028
|
+
if (parts.has("COUNT")) {
|
|
2029
|
+
const n = whole(parts.get("COUNT"));
|
|
2030
|
+
if (n === null || n < 1) return null;
|
|
2031
|
+
rule.count = n;
|
|
2032
|
+
}
|
|
2033
|
+
if (parts.has("UNTIL")) {
|
|
2034
|
+
const until = parseUntil(parts.get("UNTIL"));
|
|
2035
|
+
if (!until) return null;
|
|
2036
|
+
rule.until = until;
|
|
2037
|
+
}
|
|
2038
|
+
const byday = parts.get("BYDAY"), setpos = parts.get("BYSETPOS"), monthday = parts.get("BYMONTHDAY"), month = parts.get("BYMONTH");
|
|
2039
|
+
if (freq === "daily" || freq === "weekly") {
|
|
2040
|
+
if (setpos !== void 0 || monthday !== void 0 || month !== void 0) return null;
|
|
2041
|
+
if (byday === void 0) return rule;
|
|
2042
|
+
if (freq === "daily" && rule.interval) return null;
|
|
2043
|
+
const days = plainDays(byday);
|
|
2044
|
+
if (!days) return null;
|
|
2045
|
+
return { ...rule, freq: "weekly", weekdays: days };
|
|
2046
|
+
}
|
|
2047
|
+
if (month !== void 0) {
|
|
2048
|
+
const m = whole(month);
|
|
2049
|
+
if (freq !== "yearly" || m === null || m < 1 || m > 12) return null;
|
|
2050
|
+
rule.month = m;
|
|
2051
|
+
}
|
|
2052
|
+
if (setpos !== void 0 && byday === void 0) return null;
|
|
2053
|
+
if (byday !== void 0) {
|
|
2054
|
+
const nth = nthDay(byday, setpos);
|
|
2055
|
+
if (!nth || monthday !== void 0) return null;
|
|
2056
|
+
rule.nth = nth;
|
|
2057
|
+
} else if (monthday !== void 0) {
|
|
2058
|
+
const d = whole(monthday);
|
|
2059
|
+
if (d === null || !(d === -1 || d >= 1 && d <= 31)) return null;
|
|
2060
|
+
rule.day = d;
|
|
2061
|
+
}
|
|
2062
|
+
if (freq === "yearly" && rule.month === void 0 !== (rule.day === void 0 && rule.nth === void 0)) return null;
|
|
2063
|
+
return rule;
|
|
2064
|
+
}
|
|
2065
|
+
var pad = (n, width = 2) => String(n).padStart(width, "0");
|
|
2066
|
+
function toRRule(rule, { allDay = false } = {}) {
|
|
2067
|
+
const out = [`FREQ=${rule.freq.toUpperCase()}`];
|
|
2068
|
+
if (rule.interval && rule.interval > 1) out.push(`INTERVAL=${rule.interval}`);
|
|
2069
|
+
if (rule.month !== void 0) out.push(`BYMONTH=${rule.month}`);
|
|
2070
|
+
if (rule.day !== void 0) out.push(`BYMONTHDAY=${rule.day}`);
|
|
2071
|
+
const weekStart = rule.weekStart ?? 1;
|
|
2072
|
+
if (rule.weekdays?.length) out.push(`BYDAY=${inWeekOrder(rule.weekdays, weekStart).map((d) => DAY_CODES[d]).join(",")}`);
|
|
2073
|
+
if (rule.nth) out.push(`BYDAY=${rule.nth.week}${DAY_CODES[rule.nth.weekday]}`);
|
|
2074
|
+
if (weekStart !== 1) out.push(`WKST=${DAY_CODES[weekStart]}`);
|
|
2075
|
+
if (rule.until) {
|
|
2076
|
+
const u = rule.until;
|
|
2077
|
+
out.push(allDay ? `UNTIL=${u.getFullYear()}${pad(u.getMonth() + 1)}${pad(u.getDate())}` : `UNTIL=${u.getUTCFullYear()}${pad(u.getUTCMonth() + 1)}${pad(u.getUTCDate())}T${pad(u.getUTCHours())}${pad(u.getUTCMinutes())}${pad(u.getUTCSeconds())}Z`);
|
|
2078
|
+
}
|
|
2079
|
+
if (rule.count !== void 0) out.push(`COUNT=${rule.count}`);
|
|
2080
|
+
return `RRULE:${out.join(";")}`;
|
|
2081
|
+
}
|
|
2082
|
+
var inWeekOrder = (days, weekStart) => [...days].sort((a, b) => (a - weekStart + 7) % 7 - (b - weekStart + 7) % 7);
|
|
2083
|
+
function readRecurrence(value) {
|
|
2084
|
+
if (!value) return null;
|
|
2085
|
+
if (typeof value === "string") return parseRRule(value);
|
|
2086
|
+
if (value.until === void 0 || value.until instanceof Date) return value;
|
|
2087
|
+
const until = new Date(value.until);
|
|
2088
|
+
return Number.isNaN(until.getTime()) ? null : { ...value, until };
|
|
2089
|
+
}
|
|
2090
|
+
var daysIn = (year, month) => new Date(year, month + 1, 0).getDate();
|
|
2091
|
+
var atDay = (year, month, day, time) => new Date(year, month, day, time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds());
|
|
2092
|
+
var dayIndex = (d) => Math.round(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()) / 864e5);
|
|
2093
|
+
var isMidnight = (d) => d.getHours() === 0 && d.getMinutes() === 0 && d.getSeconds() === 0 && d.getMilliseconds() === 0;
|
|
2094
|
+
function nthWeekdayOf(year, month, week, weekday2) {
|
|
2095
|
+
const last2 = daysIn(year, month);
|
|
2096
|
+
if (week === -1) return last2 - (new Date(year, month, last2).getDay() - weekday2 + 7) % 7;
|
|
2097
|
+
const day = 1 + (weekday2 - new Date(year, month, 1).getDay() + 7) % 7 + (week - 1) * 7;
|
|
2098
|
+
return day <= last2 ? day : null;
|
|
2099
|
+
}
|
|
2100
|
+
function nthOf(date) {
|
|
2101
|
+
const d = date.getDate();
|
|
2102
|
+
return { week: d + 7 > daysIn(date.getFullYear(), date.getMonth()) ? -1 : Math.ceil(d / 7), weekday: date.getDay() };
|
|
2103
|
+
}
|
|
2104
|
+
function nthChoices(date) {
|
|
2105
|
+
const d = date.getDate(), weekday2 = date.getDay();
|
|
2106
|
+
const out = [];
|
|
2107
|
+
if (d <= 28) out.push({ week: Math.ceil(d / 7), weekday: weekday2 });
|
|
2108
|
+
if (d + 7 > daysIn(date.getFullYear(), date.getMonth())) out.push({ week: -1, weekday: weekday2 });
|
|
2109
|
+
return out;
|
|
2110
|
+
}
|
|
2111
|
+
function weekOnMoved(week, to) {
|
|
2112
|
+
const d = to.getDate();
|
|
2113
|
+
if (week === -1 && d + 7 > daysIn(to.getFullYear(), to.getMonth())) return -1;
|
|
2114
|
+
return d <= 28 ? Math.ceil(d / 7) : -1;
|
|
2115
|
+
}
|
|
2116
|
+
function withinUntil(at, until) {
|
|
2117
|
+
return at <= until || isMidnight(until) && dayIndex(at) === dayIndex(until);
|
|
2118
|
+
}
|
|
2119
|
+
function* starts(rule, first) {
|
|
2120
|
+
const interval = Math.max(1, Math.floor(rule.interval ?? 1));
|
|
2121
|
+
const firstDay = dayIndex(first);
|
|
2122
|
+
let produced = 0;
|
|
2123
|
+
const accept = (d) => {
|
|
2124
|
+
if (rule.until && !withinUntil(d, rule.until)) return false;
|
|
2125
|
+
return rule.count === void 0 || produced < rule.count;
|
|
2126
|
+
};
|
|
2127
|
+
if (rule.count !== void 0 && rule.count < 1) return;
|
|
2128
|
+
produced++;
|
|
2129
|
+
yield first;
|
|
2130
|
+
const y0 = first.getFullYear(), m0 = first.getMonth();
|
|
2131
|
+
for (let k = 0, empty = 0; k < 146100 && empty < 400 * 12; k++) {
|
|
2132
|
+
const dates = [];
|
|
2133
|
+
if (rule.freq === "daily") dates.push(atDay(y0, m0, first.getDate() + k * interval, first));
|
|
2134
|
+
else if (rule.freq === "weekly") {
|
|
2135
|
+
const weekStart = rule.weekStart ?? 1;
|
|
2136
|
+
const base = first.getDate() - (first.getDay() - weekStart + 7) % 7 + k * interval * 7;
|
|
2137
|
+
for (const wd of inWeekOrder(rule.weekdays?.length ? rule.weekdays : [first.getDay()], weekStart)) dates.push(atDay(y0, m0, base + (wd - weekStart + 7) % 7, first));
|
|
2138
|
+
} else {
|
|
2139
|
+
const monthsFrom = rule.freq === "monthly" ? k * interval : k * interval * 12;
|
|
2140
|
+
const at = new Date(y0, m0 + monthsFrom, 1);
|
|
2141
|
+
const year = at.getFullYear(), month = rule.freq === "yearly" && rule.month !== void 0 ? rule.month - 1 : at.getMonth();
|
|
2142
|
+
let day;
|
|
2143
|
+
if (rule.nth) day = nthWeekdayOf(year, month, rule.nth.week, rule.nth.weekday);
|
|
2144
|
+
else if (rule.day === -1) day = daysIn(year, month);
|
|
2145
|
+
else day = rule.day ?? first.getDate();
|
|
2146
|
+
if (day !== null && day <= daysIn(year, month)) dates.push(atDay(year, month, day, first));
|
|
2147
|
+
}
|
|
2148
|
+
let any = false;
|
|
2149
|
+
for (const d of dates) {
|
|
2150
|
+
if (dayIndex(d) <= firstDay) continue;
|
|
2151
|
+
if (!accept(d)) return;
|
|
2152
|
+
produced++;
|
|
2153
|
+
any = true;
|
|
2154
|
+
yield d;
|
|
2155
|
+
}
|
|
2156
|
+
empty = any ? 0 : empty + 1;
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
function lengthOf(event) {
|
|
2160
|
+
return event.end ? { days: dayIndex(event.end) - dayIndex(event.start), end: event.end } : null;
|
|
2161
|
+
}
|
|
2162
|
+
function occurrenceAt(event, start) {
|
|
2163
|
+
const { repeat: _repeat, exceptions: _exceptions, ...rest } = event;
|
|
2164
|
+
const length = lengthOf(event);
|
|
2165
|
+
const date = dayKey(start);
|
|
2166
|
+
const end = length ? atDay(start.getFullYear(), start.getMonth(), start.getDate() + length.days, length.end) : void 0;
|
|
2167
|
+
return { ...rest, id: `${event.id}::${date}`, start, ...end ? { end } : {}, series: { id: event.id, date } };
|
|
2168
|
+
}
|
|
2169
|
+
function stopOf(event) {
|
|
2170
|
+
if (event.allDay) {
|
|
2171
|
+
const last2 = event.end ?? event.start;
|
|
2172
|
+
return new Date(last2.getFullYear(), last2.getMonth(), last2.getDate() + 1);
|
|
2173
|
+
}
|
|
2174
|
+
return event.end ?? new Date(event.start.getTime() + 36e5);
|
|
2175
|
+
}
|
|
2176
|
+
function occurrences(event, from, to) {
|
|
2177
|
+
const rule = readRecurrence(event.repeat);
|
|
2178
|
+
if (!rule) return event.start < to && stopOf(event) > from ? [event] : [];
|
|
2179
|
+
const skip = new Set(event.exceptions ?? []);
|
|
2180
|
+
const reach = stopOf(event).getTime() - event.start.getTime();
|
|
2181
|
+
const out = [];
|
|
2182
|
+
for (const start of starts(rule, event.start)) {
|
|
2183
|
+
if (start >= to) break;
|
|
2184
|
+
if (start.getTime() + reach + 864e5 <= from.getTime()) continue;
|
|
2185
|
+
if (skip.has(dayKey(start))) continue;
|
|
2186
|
+
const occurrence = occurrenceAt(event, start);
|
|
2187
|
+
if (stopOf(occurrence) > from) out.push(occurrence);
|
|
2188
|
+
}
|
|
2189
|
+
return out;
|
|
2190
|
+
}
|
|
2191
|
+
function startsBefore(rule, first, date) {
|
|
2192
|
+
let n = 0;
|
|
2193
|
+
for (const start of starts(rule, first)) {
|
|
2194
|
+
if (dayKey(start) >= date) break;
|
|
2195
|
+
n++;
|
|
2196
|
+
}
|
|
2197
|
+
return n;
|
|
2198
|
+
}
|
|
2199
|
+
var asWritten = (event, rule) => typeof event.repeat === "string" ? toRRule(rule, { allDay: event.allDay }) : rule;
|
|
2200
|
+
var shiftKey = (key, days) => {
|
|
2201
|
+
const [y, m, d] = key.split("-").map(Number);
|
|
2202
|
+
return dayKey(new Date(y, m - 1, d + days));
|
|
2203
|
+
};
|
|
2204
|
+
var occurrenceOnDay = (series, date) => {
|
|
2205
|
+
const [y, m, d] = date.split("-").map(Number);
|
|
2206
|
+
return occurrenceAt(series, atDay(y, m - 1, d, series.start));
|
|
2207
|
+
};
|
|
2208
|
+
var editedOf = (events, seriesId) => events.filter((e) => e.series?.id === seriesId && e.id !== seriesId);
|
|
2209
|
+
function occurrenceOn(series, date, events) {
|
|
2210
|
+
const edited = events && editedOf(events, series.id).find((e) => e.series.date === date);
|
|
2211
|
+
if (edited) return edited;
|
|
2212
|
+
const [y, m, d] = date.split("-").map(Number);
|
|
2213
|
+
return occurrences(series, new Date(y, m - 1, d), new Date(y, m - 1, d + 1)).find((o) => "series" in o && o.series?.date === date);
|
|
2214
|
+
}
|
|
2215
|
+
var editOf = (changes) => {
|
|
2216
|
+
if (!changes) return {};
|
|
2217
|
+
const { id: _id, repeat: _repeat, exceptions: _exceptions, ...rest } = changes;
|
|
2218
|
+
delete rest.series;
|
|
2219
|
+
return rest;
|
|
2220
|
+
};
|
|
2221
|
+
var repeatChanged = (series, changes) => {
|
|
2222
|
+
if (!changes || !("repeat" in changes)) return false;
|
|
2223
|
+
const given = changes.repeat;
|
|
2224
|
+
if (given === series.repeat) return false;
|
|
2225
|
+
const a = readRecurrence(given), b = readRecurrence(series.repeat);
|
|
2226
|
+
return !(a && b && sameRecurrence(a, b));
|
|
2227
|
+
};
|
|
2228
|
+
function sameValue(a, b) {
|
|
2229
|
+
if (a instanceof Date || b instanceof Date) return a instanceof Date && b instanceof Date && a.getTime() === b.getTime();
|
|
2230
|
+
if (a && b && typeof a === "object" && typeof b === "object") return JSON.stringify(a) === JSON.stringify(b);
|
|
2231
|
+
return a === b;
|
|
2232
|
+
}
|
|
2233
|
+
function editFrom(opened, series, changes) {
|
|
2234
|
+
const was = opened;
|
|
2235
|
+
const edit = {};
|
|
2236
|
+
for (const [key, value] of Object.entries(editOf(changes))) if (!sameValue(value, was[key])) edit[key] = value;
|
|
2237
|
+
if (repeatChanged(series, changes)) edit.repeat = changes.repeat;
|
|
2238
|
+
return edit;
|
|
2239
|
+
}
|
|
2240
|
+
function moveRule(rule, days, to) {
|
|
2241
|
+
const next = { ...rule };
|
|
2242
|
+
if (rule.weekdays?.length) next.weekdays = rule.weekdays.map((d) => ((d + days) % 7 + 7) % 7).sort((a, b) => a - b);
|
|
2243
|
+
if (rule.freq === "monthly" || rule.freq === "yearly") {
|
|
2244
|
+
if (rule.nth) next.nth = { week: weekOnMoved(rule.nth.week, to), weekday: to.getDay() };
|
|
2245
|
+
else if (rule.day === -1) {
|
|
2246
|
+
if (to.getDate() !== daysIn(to.getFullYear(), to.getMonth())) next.day = to.getDate();
|
|
2247
|
+
} else if (rule.day !== void 0) next.day = to.getDate();
|
|
2248
|
+
if (rule.freq === "yearly" && rule.month !== void 0) next.month = to.getMonth() + 1;
|
|
2249
|
+
}
|
|
2250
|
+
return next;
|
|
2251
|
+
}
|
|
2252
|
+
function onMovedRule(rule, start, days) {
|
|
2253
|
+
const endless = { ...rule, until: void 0, count: void 0 };
|
|
2254
|
+
return (key) => {
|
|
2255
|
+
const shifted = shiftKey(key, days);
|
|
2256
|
+
const [y, m, d] = shifted.split("-").map(Number);
|
|
2257
|
+
const target = dayIndex(new Date(y, m - 1, d));
|
|
2258
|
+
let found = null;
|
|
2259
|
+
for (const at of starts(endless, start)) {
|
|
2260
|
+
const i = dayIndex(at);
|
|
2261
|
+
if (i > target + 7) break;
|
|
2262
|
+
if (i >= target - 7 && (!found || Math.abs(i - target) < Math.abs(dayIndex(found) - target))) found = at;
|
|
2263
|
+
}
|
|
2264
|
+
return found ? dayKey(found) : shifted;
|
|
2265
|
+
};
|
|
2266
|
+
}
|
|
2267
|
+
var sameClock = (a, b) => a.getHours() === b.getHours() && a.getMinutes() === b.getMinutes() && a.getSeconds() === b.getSeconds() && a.getMilliseconds() === b.getMilliseconds();
|
|
2268
|
+
var spanOf = (event) => event.end ? dayIndex(event.end) - dayIndex(event.start) : null;
|
|
2269
|
+
function changeSeries(series, occurrence, changes) {
|
|
2270
|
+
const at = typeof occurrence === "string" ? occurrenceOnDay(series, occurrence) : occurrence;
|
|
2271
|
+
const { start: newStart, end: newEnd, ...rest } = editOf(changes);
|
|
2272
|
+
const next = { ...series, ...rest };
|
|
2273
|
+
const moveBy = (from, to, base) => atDay(base.getFullYear(), base.getMonth(), base.getDate() + dayIndex(to) - dayIndex(from), sameClock(to, from) ? base : to);
|
|
2274
|
+
let days = 0;
|
|
2275
|
+
if (newStart) {
|
|
2276
|
+
days = dayIndex(newStart) - dayIndex(at.start);
|
|
2277
|
+
next.start = moveBy(at.start, newStart, series.start);
|
|
2278
|
+
}
|
|
2279
|
+
if (newEnd) {
|
|
2280
|
+
const from = at.end ?? at.start;
|
|
2281
|
+
next.end = moveBy(from, newEnd, series.end ?? series.start);
|
|
2282
|
+
}
|
|
2283
|
+
const rule = readRecurrence(series.repeat);
|
|
2284
|
+
let moveKey = (key) => shiftKey(key, days);
|
|
2285
|
+
const moveExceptions = () => {
|
|
2286
|
+
if (days !== 0 && series.exceptions?.length) next.exceptions = series.exceptions.map(moveKey);
|
|
2287
|
+
};
|
|
2288
|
+
if (repeatChanged(series, changes)) {
|
|
2289
|
+
if (changes.repeat) {
|
|
2290
|
+
next.repeat = changes.repeat;
|
|
2291
|
+
moveExceptions();
|
|
2292
|
+
} else {
|
|
2293
|
+
delete next.repeat;
|
|
2294
|
+
delete next.exceptions;
|
|
2295
|
+
}
|
|
2296
|
+
} else if (days !== 0 && rule && newStart) {
|
|
2297
|
+
const moved = moveRule(rule, days, newStart);
|
|
2298
|
+
next.repeat = asWritten(series, moved);
|
|
2299
|
+
if (moved.nth) {
|
|
2300
|
+
const from = next.start;
|
|
2301
|
+
const anchor = (k) => {
|
|
2302
|
+
const at2 = new Date(from.getFullYear() + (moved.freq === "yearly" ? k : 0), (moved.freq === "yearly" && moved.month !== void 0 ? moved.month - 1 : from.getMonth()) + (moved.freq === "monthly" ? k : 0), 1);
|
|
2303
|
+
const d = nthWeekdayOf(at2.getFullYear(), at2.getMonth(), moved.nth.week, moved.nth.weekday) ?? nthWeekdayOf(at2.getFullYear(), at2.getMonth(), -1, moved.nth.weekday);
|
|
2304
|
+
return atDay(at2.getFullYear(), at2.getMonth(), d, from);
|
|
2305
|
+
};
|
|
2306
|
+
let first = anchor(0);
|
|
2307
|
+
if (dayIndex(first) < dayIndex(from)) first = anchor(1);
|
|
2308
|
+
const extra = dayIndex(first) - dayIndex(from);
|
|
2309
|
+
if (extra) {
|
|
2310
|
+
next.start = first;
|
|
2311
|
+
if (next.end) next.end = atDay(next.end.getFullYear(), next.end.getMonth(), next.end.getDate() + extra, next.end);
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
moveKey = onMovedRule(moved, next.start, days);
|
|
2315
|
+
moveExceptions();
|
|
2316
|
+
}
|
|
2317
|
+
return { next, moveKey };
|
|
2318
|
+
}
|
|
2319
|
+
function splitWith(series, date, id, at, changes) {
|
|
2320
|
+
const rule = readRecurrence(series.repeat);
|
|
2321
|
+
const firstDate = dayKey(series.start);
|
|
2322
|
+
if (!rule || date <= firstDate) {
|
|
2323
|
+
if (!changes) return { after: series, moveKey: (key) => key };
|
|
2324
|
+
const { next: next2, moveKey: moveKey2 } = changeSeries(series, typeof at === "string" ? at <= firstDate ? firstDate : at : at, changes);
|
|
2325
|
+
return { after: next2, moveKey: moveKey2 };
|
|
2326
|
+
}
|
|
2327
|
+
const [y, m, d] = date.split("-").map(Number);
|
|
2328
|
+
const first = occurrenceOnDay(series, date);
|
|
2329
|
+
const exceptions = series.exceptions ?? [];
|
|
2330
|
+
const counted = rule.count !== void 0 ? startsBefore(rule, series.start, date) : 0;
|
|
2331
|
+
const beforeRule = { ...rule };
|
|
2332
|
+
if (rule.count !== void 0) beforeRule.count = counted;
|
|
2333
|
+
else {
|
|
2334
|
+
delete beforeRule.until;
|
|
2335
|
+
beforeRule.until = series.allDay ? new Date(y, m - 1, d - 1) : new Date(y, m - 1, d - 1, 23, 59, 59);
|
|
2336
|
+
}
|
|
2337
|
+
const afterRule = { ...rule };
|
|
2338
|
+
if (rule.count !== void 0) afterRule.count = rule.count - counted;
|
|
2339
|
+
const before = { ...series, repeat: asWritten(series, beforeRule), exceptions: exceptions.filter((x) => x < date) };
|
|
2340
|
+
const after = { ...series, id, start: first.start, ...first.end ? { end: first.end } : {}, repeat: asWritten(series, afterRule), exceptions: exceptions.filter((x) => x >= date) };
|
|
2341
|
+
if (!changes) return { before, after, moveKey: (key) => key };
|
|
2342
|
+
const edit = repeatChanged(series, changes) ? changes : editOf(changes);
|
|
2343
|
+
const { next, moveKey } = changeSeries(after, typeof at === "string" ? date : at, edit);
|
|
2344
|
+
return { before, after: next, moveKey };
|
|
2345
|
+
}
|
|
2346
|
+
function detachOccurrence(series, date, id = `${series.id}-${date}`, changes) {
|
|
2347
|
+
return {
|
|
2348
|
+
series: { ...series, exceptions: [.../* @__PURE__ */ new Set([...series.exceptions ?? [], date])].sort() },
|
|
2349
|
+
event: { ...occurrenceOnDay(series, date), ...editOf(changes), id }
|
|
2350
|
+
};
|
|
2351
|
+
}
|
|
2352
|
+
var NOT_FOLLOWED = /* @__PURE__ */ new Set(["id", "series", "start", "end", "repeat", "exceptions"]);
|
|
2353
|
+
function follow(edited, was, now) {
|
|
2354
|
+
const out = { ...edited };
|
|
2355
|
+
const before = was, after = now;
|
|
2356
|
+
for (const key of /* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])) {
|
|
2357
|
+
if (NOT_FOLLOWED.has(key) || !sameValue(out[key], before[key])) continue;
|
|
2358
|
+
if (after[key] === void 0) delete out[key];
|
|
2359
|
+
else out[key] = after[key];
|
|
2360
|
+
}
|
|
2361
|
+
const ownDay = dayIndex(edited.start) !== dayIndex(was.start);
|
|
2362
|
+
const ownTimes = !sameClock(edited.start, was.start) || spanOf(edited) !== spanOf(was) || !!edited.end && !!was.end && !sameClock(edited.end, was.end);
|
|
2363
|
+
const day = ownDay ? edited.start : now.start;
|
|
2364
|
+
const times = ownTimes ? edited : now;
|
|
2365
|
+
const start = atDay(day.getFullYear(), day.getMonth(), day.getDate(), times.start);
|
|
2366
|
+
out.start = start;
|
|
2367
|
+
const span = spanOf(times);
|
|
2368
|
+
if (times.end && span !== null) out.end = atDay(start.getFullYear(), start.getMonth(), start.getDate() + span, times.end);
|
|
2369
|
+
else delete out.end;
|
|
2370
|
+
return out;
|
|
2371
|
+
}
|
|
2372
|
+
function carry(old, next, linked, moveKey, changed, opened, edit) {
|
|
2373
|
+
if (!linked.length) return { next, save: [], remove: [] };
|
|
2374
|
+
if (changed) {
|
|
2375
|
+
const freed = new Set(linked.map((e) => moveKey(e.series.date)));
|
|
2376
|
+
return { next: next.exceptions ? { ...next, exceptions: next.exceptions.filter((x) => !freed.has(x)) } : next, save: [], remove: linked.map((e) => e.id) };
|
|
2377
|
+
}
|
|
2378
|
+
const save = linked.map((e) => {
|
|
2379
|
+
const date = moveKey(e.series.date);
|
|
2380
|
+
const followed = follow(e, occurrenceOnDay(old, e.series.date), occurrenceOnDay(next, date));
|
|
2381
|
+
return { ...followed, ...e.id === opened?.id ? editOf(edit) : {}, series: { id: next.id, date } };
|
|
2382
|
+
});
|
|
2383
|
+
return { next, save, remove: [] };
|
|
2384
|
+
}
|
|
2385
|
+
function findSeries(events, occurrence) {
|
|
2386
|
+
const stored = events.find((e) => e.id === occurrence.id);
|
|
2387
|
+
const link = (stored ?? occurrence).series;
|
|
2388
|
+
const series = link ? events.find((e) => e.id === link.id && readRecurrence(e.repeat) !== null) : void 0;
|
|
2389
|
+
return { series, stored, date: link?.date };
|
|
2390
|
+
}
|
|
2391
|
+
function commit(events, save, remove) {
|
|
2392
|
+
const gone = new Set(remove);
|
|
2393
|
+
const saved = new Map(save.map((e) => [e.id, e]));
|
|
2394
|
+
const had = new Set(events.map((e) => e.id));
|
|
2395
|
+
return { events: [...events.filter((e) => !gone.has(e.id)).map((e) => saved.get(e.id) ?? e), ...save.filter((e) => !had.has(e.id))], save, remove };
|
|
2396
|
+
}
|
|
2397
|
+
function saveOccurrence(events, occurrence, scope, changes, newId) {
|
|
2398
|
+
const { series, stored, date } = findSeries(events, occurrence);
|
|
2399
|
+
if (!series || date === void 0) return commit(events, stored ? [{ ...stored, ...editOf(changes) }] : [], []);
|
|
2400
|
+
const opened = stored ?? occurrenceOnDay(series, date);
|
|
2401
|
+
const edit = editFrom(opened, series, changes);
|
|
2402
|
+
if (scope === "this") {
|
|
2403
|
+
if (stored) return commit(events, [{ ...stored, ...editOf(edit) }], []);
|
|
2404
|
+
const { series: kept, event } = detachOccurrence(series, date, newId, edit);
|
|
2405
|
+
return commit(events, [kept, event], []);
|
|
2406
|
+
}
|
|
2407
|
+
const linked = editedOf(events, series.id);
|
|
2408
|
+
const changed = repeatChanged(series, edit);
|
|
2409
|
+
if (scope === "following" && date > dayKey(series.start)) {
|
|
2410
|
+
const { before, after, moveKey: moveKey2 } = splitWith(series, date, newId, opened, edit);
|
|
2411
|
+
const carried2 = carry(series, after, linked.filter((e) => e.series.date >= date), moveKey2, changed, stored, edit);
|
|
2412
|
+
return commit(events, [...before ? [before] : [], carried2.next, ...carried2.save], carried2.remove);
|
|
2413
|
+
}
|
|
2414
|
+
const { next, moveKey } = changeSeries(series, opened, edit);
|
|
2415
|
+
const carried = carry(series, next, linked, moveKey, changed, stored, edit);
|
|
2416
|
+
return commit(events, [carried.next, ...carried.save], carried.remove);
|
|
2417
|
+
}
|
|
2418
|
+
function deleteOccurrence(events, occurrence, scope) {
|
|
2419
|
+
const { series, stored, date } = findSeries(events, occurrence);
|
|
2420
|
+
if (!series || date === void 0) return commit(events, [], stored ? [stored.id] : []);
|
|
2421
|
+
if (scope === "this") return stored ? commit(events, [], [stored.id]) : commit(events, [detachOccurrence(series, date).series], []);
|
|
2422
|
+
const linked = editedOf(events, series.id);
|
|
2423
|
+
if (scope === "following" && date > dayKey(series.start)) {
|
|
2424
|
+
const { before } = splitWith(series, date, series.id, date);
|
|
2425
|
+
return commit(events, before ? [before] : [], linked.filter((e) => e.series.date >= date).map((e) => e.id));
|
|
2426
|
+
}
|
|
2427
|
+
return commit(events, [], [series.id, ...linked.map((e) => e.id)]);
|
|
2428
|
+
}
|
|
2429
|
+
function countEdited(events, occurrence) {
|
|
2430
|
+
const { series, date } = findSeries(events, occurrence);
|
|
2431
|
+
if (!series || date === void 0) return { following: 0, all: 0 };
|
|
2432
|
+
const linked = editedOf(events, series.id);
|
|
2433
|
+
return { following: date > dayKey(series.start) ? linked.filter((e) => e.series.date >= date).length : linked.length, all: linked.length };
|
|
2434
|
+
}
|
|
2435
|
+
var formats = localeCache(128);
|
|
2436
|
+
function format(options, date, locale) {
|
|
2437
|
+
return formats(`${locale ?? ""}|${JSON.stringify(options)}`, () => new Intl.DateTimeFormat(locale, options)).format(date);
|
|
2438
|
+
}
|
|
2439
|
+
var weekdayName = (d, locale) => format({ weekday: "long" }, new Date(2026, 0, 4 + d), locale);
|
|
2440
|
+
var monthName = (m, locale) => format({ month: "long" }, new Date(2026, m - 1, 1), locale);
|
|
2441
|
+
var ORDINAL = { 1: "first", 2: "second", 3: "third", 4: "fourth", [-1]: "last" };
|
|
2442
|
+
var list = (items) => items.length < 2 ? items.join("") : `${items.slice(0, -1).join(", ")} and ${items[items.length - 1]}`;
|
|
2443
|
+
var every = (n, one, many) => n > 1 ? `Every ${n} ${many}` : `Every ${one}`;
|
|
2444
|
+
function describeRecurrence(rule, start, locale = formatLocale()) {
|
|
2445
|
+
const n = Math.max(1, Math.floor(rule.interval ?? 1));
|
|
2446
|
+
const weekStart = rule.weekStart ?? 1;
|
|
2447
|
+
let text;
|
|
2448
|
+
if (rule.freq === "daily") text = every(n, "day", "days");
|
|
2449
|
+
else if (rule.freq === "weekly") {
|
|
2450
|
+
const days = inWeekOrder(rule.weekdays?.length ? rule.weekdays : [start.getDay()], weekStart);
|
|
2451
|
+
if (days.length === 7) text = every(n, "day", "weeks on every day");
|
|
2452
|
+
else if (n === 1 && days.join() === "1,2,3,4,5") text = "Every weekday (Monday to Friday)";
|
|
2453
|
+
else text = `${every(n, "week", "weeks")} on ${list(days.map((d) => weekdayName(d, locale)))}`;
|
|
2454
|
+
} else {
|
|
2455
|
+
const nth = rule.nth ? `the ${ORDINAL[rule.nth.week]} ${weekdayName(rule.nth.weekday, locale)}` : void 0;
|
|
2456
|
+
if (rule.freq === "monthly") {
|
|
2457
|
+
const on = nth ?? (rule.day === -1 ? "the last day" : `day ${rule.day ?? start.getDate()}`);
|
|
2458
|
+
text = `${every(n, "month", "months")} on ${on}`;
|
|
2459
|
+
} else {
|
|
2460
|
+
const month = rule.month ?? start.getMonth() + 1;
|
|
2461
|
+
const on = nth ? `${nth} of ${monthName(month, locale)}` : rule.day === -1 ? `the last day of ${monthName(month, locale)}` : (
|
|
2462
|
+
// a leap year, so 29 February reads as itself
|
|
2463
|
+
format({ day: "numeric", month: "long" }, new Date(2028, month - 1, rule.day ?? start.getDate()), locale)
|
|
2464
|
+
);
|
|
2465
|
+
text = `${every(n, "year", "years")} on ${on}`;
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
if (rule.until) text += `, until ${format({ day: "numeric", month: "long", year: "numeric" }, rule.until, locale)}`;
|
|
2469
|
+
else if (rule.count !== void 0) text += rule.count === 1 ? ", once" : `, ${rule.count} times`;
|
|
2470
|
+
return text;
|
|
2471
|
+
}
|
|
2472
|
+
function recurrencePresets(start, locale = formatLocale()) {
|
|
2473
|
+
const rules = [{ freq: "daily" }];
|
|
2474
|
+
const weekday2 = start.getDay();
|
|
2475
|
+
if (weekday2 >= 1 && weekday2 <= 5) rules.push({ freq: "weekly", weekdays: [1, 2, 3, 4, 5] });
|
|
2476
|
+
rules.push({ freq: "weekly" }, ...nthChoices(start).map((nth) => ({ freq: "monthly", nth })), { freq: "monthly" });
|
|
2477
|
+
if (start.getDate() === daysIn(start.getFullYear(), start.getMonth())) rules.push({ freq: "monthly", day: -1 });
|
|
2478
|
+
rules.push({ freq: "yearly" });
|
|
2479
|
+
return rules.map((rule) => ({ rule, label: describeRecurrence(rule, start, locale) }));
|
|
2480
|
+
}
|
|
2481
|
+
function sameRecurrence(a, b) {
|
|
2482
|
+
if (!a || !b) return a === b;
|
|
2483
|
+
const norm = (r) => toRRule({ ...r, weekdays: r.weekdays?.length ? [...r.weekdays].sort() : void 0 });
|
|
2484
|
+
return norm(a) === norm(b);
|
|
2485
|
+
}
|
|
2486
|
+
var DAYS_MESSAGE = "Choose at least one day";
|
|
2487
|
+
var UNTIL_MESSAGE = "The end date must be after the event starts";
|
|
2488
|
+
var UNTIL_MISSING = "Enter the end date";
|
|
2489
|
+
var UNITS = { daily: ["day", "days"], weekly: ["week", "weeks"], monthly: ["month", "months"], yearly: ["year", "years"] };
|
|
2490
|
+
var ORDINAL2 = { 1: "first", 2: "second", 3: "third", 4: "fourth", [-1]: "last" };
|
|
2491
|
+
var weekdayName2 = (d, width, locale) => new Intl.DateTimeFormat(locale, { weekday: width }).format(new Date(2026, 0, 4 + d));
|
|
2492
|
+
var daysIn2 = (d) => new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate();
|
|
2493
|
+
var clean = (rule) => Object.fromEntries(Object.entries(rule).filter(([, v]) => v !== void 0));
|
|
2494
|
+
var kindOf = (r) => [r.freq, r.weekdays?.length ? "days" : "", r.nth ? r.nth.week === -1 ? "nth-last" : "nth" : "", r.day === -1 ? "last" : ""].join(":");
|
|
2495
|
+
var endOfDay = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate(), 23, 59, 59);
|
|
2496
|
+
var noDays = (r) => r?.freq === "weekly" && Array.isArray(r.weekdays) && r.weekdays.length === 0;
|
|
2497
|
+
var PENDING_OPTIONS = [{ id: "pending", label: "" }];
|
|
2498
|
+
function RecurrencePicker({ value, onChange: onChangeProp, start, label, weekStartsOn, className, ...wiring }) {
|
|
2499
|
+
const onChange = useReportedChange(onChangeProp, value);
|
|
2500
|
+
const field = useField();
|
|
2501
|
+
const weekStart = useWeekStart(weekStartsOn);
|
|
2502
|
+
const locale = useFormatLocale();
|
|
2503
|
+
const hydrated = useHydrated();
|
|
2504
|
+
const base = useId();
|
|
2505
|
+
const ids = { summary: `${base}-summary`, interval: `${base}-interval`, days: `${base}-days`, daysError: `${base}-days-error`, untilError: `${base}-until-error`, count: `${base}-count` };
|
|
2506
|
+
const startKey = dayKey(start);
|
|
2507
|
+
const presets = useMemo(() => recurrencePresets(start, locale), [startKey, locale]);
|
|
2508
|
+
const rule = readRecurrence(value);
|
|
2509
|
+
const unreadable = value !== null && !rule;
|
|
2510
|
+
const presetIndex = rule && !noDays(rule) ? presets.findIndex((p) => sameRecurrence(p.rule, rule)) : -1;
|
|
2511
|
+
const [customOpen, setCustomOpen] = useState(() => !!rule && presetIndex < 0);
|
|
2512
|
+
const openRule = rule && (customOpen || presetIndex < 0) ? rule : null;
|
|
2513
|
+
const choice = value === null ? "none" : unreadable ? "unreadable" : openRule ? "custom" : `preset-${presetIndex}`;
|
|
2514
|
+
const [untilPending, setUntilPending] = useState(false);
|
|
2515
|
+
const lastStart = useRef(start);
|
|
2516
|
+
useEffect(() => {
|
|
2517
|
+
const before = lastStart.current;
|
|
2518
|
+
lastStart.current = start;
|
|
2519
|
+
if (dayKey(before) === startKey || !rule || customOpen) return;
|
|
2520
|
+
const was = recurrencePresets(before, locale).find((p) => sameRecurrence(p.rule, rule));
|
|
2521
|
+
const now2 = was && (presets.find((p) => kindOf(p.rule) === kindOf(was.rule)) ?? (was.rule.nth ? presets.find((p) => !!p.rule.nth) : void 0));
|
|
2522
|
+
if (now2 && !sameRecurrence(now2.rule, rule)) onChangeProp(now2.rule);
|
|
2523
|
+
}, [startKey]);
|
|
2524
|
+
const explicit = (r) => {
|
|
2525
|
+
const week = weekStart !== 1 ? { weekStart } : {};
|
|
2526
|
+
if (!r || r.freq === "weekly" && r.weekdays === void 0) return clean({ ...r ?? {}, freq: "weekly", weekdays: [start.getDay()], ...week });
|
|
2527
|
+
if (r.freq === "monthly" && r.day === void 0 && !r.nth) return { ...r, day: start.getDate() };
|
|
2528
|
+
if (r.freq === "yearly" && r.month === void 0) return { ...r, month: start.getMonth() + 1, day: start.getDate() };
|
|
2529
|
+
return r;
|
|
2530
|
+
};
|
|
2531
|
+
const edit = (patch) => onChange(clean({ ...explicit(rule), ...patch }));
|
|
2532
|
+
const custom = openRule ? explicit(openRule) : null;
|
|
2533
|
+
const unit = (freq) => {
|
|
2534
|
+
const keep = { interval: rule?.interval, until: rule?.until, count: rule?.count };
|
|
2535
|
+
const week = weekStart !== 1 ? { weekStart } : {};
|
|
2536
|
+
const by = {
|
|
2537
|
+
daily: { freq },
|
|
2538
|
+
weekly: { freq, weekdays: [start.getDay()], ...week },
|
|
2539
|
+
monthly: { freq, day: start.getDate() },
|
|
2540
|
+
yearly: { freq, month: start.getMonth() + 1, day: start.getDate() }
|
|
2541
|
+
};
|
|
2542
|
+
onChange(clean({ ...by[freq], ...keep }));
|
|
2543
|
+
};
|
|
2544
|
+
const form = useOptionalFormContext();
|
|
2545
|
+
const check = (r, s, open, pending) => ({
|
|
2546
|
+
// every day taken off: an implied rule (no days written) repeats on the start's day, so it has one
|
|
2547
|
+
days: open && noDays(r) ? DAYS_MESSAGE : void 0,
|
|
2548
|
+
until: open && pending && !r?.until ? UNTIL_MISSING : r?.until && dayKey(r.until) <= s ? UNTIL_MESSAGE : void 0
|
|
2549
|
+
});
|
|
2550
|
+
const latest = useLatest({ rule, startKey, custom: !!custom, untilPending });
|
|
2551
|
+
const problems = () => check(latest.current.rule, latest.current.startKey, latest.current.custom, latest.current.untilPending);
|
|
2552
|
+
const register = form?.register;
|
|
2553
|
+
useEffect(() => register?.(ids.days, () => problems().days), [register, ids.days]);
|
|
2554
|
+
useEffect(() => register?.(ids.untilError, () => problems().until), [register, ids.untilError]);
|
|
2555
|
+
const now = check(rule, startKey, !!custom, untilPending);
|
|
2556
|
+
const setError = form?.setError;
|
|
2557
|
+
const shownDays = form ? form.errors[ids.days] : now.days;
|
|
2558
|
+
const shownUntil = form ? form.errors[ids.untilError] : now.until;
|
|
2559
|
+
useEffect(() => {
|
|
2560
|
+
if (shownDays !== void 0 && shownDays !== now.days) setError?.(ids.days, now.days);
|
|
2561
|
+
if (shownUntil !== void 0 && shownUntil !== now.until) setError?.(ids.untilError, now.until);
|
|
2562
|
+
});
|
|
2563
|
+
const options = [
|
|
2564
|
+
{ id: "none", label: "Does not repeat" },
|
|
2565
|
+
...presets.map((p, i) => ({ id: `preset-${i}`, label: p.label })),
|
|
2566
|
+
...unreadable ? [{ id: "unreadable", label: "Custom repeat" }] : [],
|
|
2567
|
+
{ id: "custom", label: "Custom\u2026" }
|
|
2568
|
+
];
|
|
2569
|
+
const choose = (id) => {
|
|
2570
|
+
if (id === "unreadable") return;
|
|
2571
|
+
setUntilPending(false);
|
|
2572
|
+
if (id === "none") {
|
|
2573
|
+
setCustomOpen(false);
|
|
2574
|
+
onChange(null);
|
|
2575
|
+
return;
|
|
2576
|
+
}
|
|
2577
|
+
if (id === "custom") {
|
|
2578
|
+
setCustomOpen(true);
|
|
2579
|
+
onChange(explicit(rule));
|
|
2580
|
+
return;
|
|
2581
|
+
}
|
|
2582
|
+
setCustomOpen(false);
|
|
2583
|
+
onChange(presets[Number(id.slice("preset-".length))].rule);
|
|
2584
|
+
};
|
|
2585
|
+
const summary = rule && !noDays(rule) ? describeRecurrence(rule, start, locale) : unreadable ? "Repeats by a rule set in another app. Choose another to replace it." : null;
|
|
2586
|
+
const describedBy = [wiring["aria-describedby"], summary ? ids.summary : void 0].filter(Boolean).join(" ") || void 0;
|
|
2587
|
+
const order = Array.from({ length: 7 }, (_, i) => (weekStart + i) % 7);
|
|
2588
|
+
const interval = custom?.interval ?? 1;
|
|
2589
|
+
const monthDay = custom?.day !== void 0 && custom.day > 0 ? custom.day : start.getDate();
|
|
2590
|
+
const nths = nthChoices(start);
|
|
2591
|
+
if (custom?.nth && !nths.some((n) => n.week === custom.nth.week && n.weekday === custom.nth.weekday)) nths.unshift(custom.nth);
|
|
2592
|
+
const nthId = (n) => `nth:${n.week}:${n.weekday}`;
|
|
2593
|
+
const monthlyOn = custom?.nth ? nthId(custom.nth) : custom?.day === -1 ? "last" : "day";
|
|
2594
|
+
const ends = custom?.until ? "until" : custom?.count !== void 0 ? "count" : untilPending ? "until" : "never";
|
|
2595
|
+
if (!hydrated) {
|
|
2596
|
+
return /* @__PURE__ */ jsxs("div", { "data-gs": "recurrence-picker", "data-recurrence-pending": "", "aria-busy": "true", className: cn("space-y-ds-2", className), children: [
|
|
2597
|
+
/* @__PURE__ */ jsx(Dropdown, { ...wiring, label: field ? void 0 : label ?? "Repeat", options: PENDING_OPTIONS, value: "pending", onChange: () => {
|
|
2598
|
+
} }),
|
|
2599
|
+
(rule && !noDays(rule) || unreadable) && /* @__PURE__ */ jsx("p", { "aria-hidden": "true", className: "text-xs", children: "\xA0" })
|
|
2600
|
+
] });
|
|
2601
|
+
}
|
|
2602
|
+
return /* @__PURE__ */ jsxs("div", { "data-gs": "recurrence-picker", className: cn("space-y-ds-2", className), children: [
|
|
2603
|
+
/* @__PURE__ */ jsx(
|
|
2604
|
+
Dropdown,
|
|
2605
|
+
{
|
|
2606
|
+
...wiring,
|
|
2607
|
+
"aria-describedby": describedBy,
|
|
2608
|
+
label: field ? void 0 : label ?? "Repeat",
|
|
2609
|
+
options,
|
|
2610
|
+
value: choice,
|
|
2611
|
+
onChange: (v) => choose(v)
|
|
2612
|
+
}
|
|
2613
|
+
),
|
|
2614
|
+
custom && /* @__PURE__ */ jsx(OutsideField, { children: /* @__PURE__ */ jsxs("div", { "data-gs": "recurrence-custom", className: "space-y-ds-4 pl-ds-4 border-l-[length:var(--ds-border-width)] border-[var(--ds-border-default)]", children: [
|
|
2615
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-ds-2", children: [
|
|
2616
|
+
/* @__PURE__ */ jsx("label", { htmlFor: ids.interval, className: "text-sm text-[var(--ds-text-primary)]", children: "Every" }),
|
|
2617
|
+
/* @__PURE__ */ jsx(NumberInput, { id: ids.interval, size: "sm", value: interval, min: 1, max: 99, onChange: (n) => edit({ interval: n > 1 ? n : void 0 }), className: "w-28" }),
|
|
2618
|
+
/* @__PURE__ */ jsx(
|
|
2619
|
+
Dropdown,
|
|
2620
|
+
{
|
|
2621
|
+
"aria-label": "Days, weeks, months or years",
|
|
2622
|
+
size: "sm",
|
|
2623
|
+
className: "w-36",
|
|
2624
|
+
options: Object.keys(UNITS).map((f) => ({ id: f, label: UNITS[f][interval > 1 ? 1 : 0] })),
|
|
2625
|
+
value: custom.freq,
|
|
2626
|
+
onChange: (v) => unit(v)
|
|
2627
|
+
}
|
|
2628
|
+
)
|
|
2629
|
+
] }),
|
|
2630
|
+
custom.freq === "weekly" && /* @__PURE__ */ jsxs("div", { className: "space-y-ds-2", children: [
|
|
2631
|
+
/* @__PURE__ */ jsx("p", { "aria-hidden": "true", className: "text-sm font-medium text-[var(--ds-text-primary)]", children: "On" }),
|
|
2632
|
+
/* @__PURE__ */ jsx("div", { role: "group", id: ids.days, "aria-label": "Repeat on", "aria-invalid": !!shownDays || void 0, "aria-describedby": shownDays ? ids.daysError : void 0, className: "flex flex-wrap gap-ds-1.5", children: order.map((d) => {
|
|
2633
|
+
const on = !!custom.weekdays?.includes(d);
|
|
2634
|
+
return /* @__PURE__ */ jsx(
|
|
2635
|
+
"button",
|
|
2636
|
+
{
|
|
2637
|
+
type: "button",
|
|
2638
|
+
role: "checkbox",
|
|
2639
|
+
"aria-checked": on,
|
|
2640
|
+
"aria-label": weekdayName2(d, "long", locale),
|
|
2641
|
+
onClick: () => edit({ weekdays: (on ? (custom.weekdays ?? []).filter((x) => x !== d) : [...custom.weekdays ?? [], d]).sort((a, b) => a - b) }),
|
|
2642
|
+
className: cn(
|
|
2643
|
+
"inline-flex h-8 min-w-8 items-center justify-center px-ds-2 rounded-[var(--ds-radius-full)] text-xs font-medium",
|
|
2644
|
+
"border-[length:var(--ds-border-width)] cursor-pointer select-none outline-none transition-colors",
|
|
2645
|
+
"focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
2646
|
+
// chosen: the accent's readable pair, so its text reads 4.5:1 in every theme (the house's one way
|
|
2647
|
+
// to colour text on a colour, as the Calendar's accent events), and the checked border at 3:1
|
|
2648
|
+
// marking the state; the tick colour on the checked fill read 3.2:1 in three themes
|
|
2649
|
+
on ? "bg-[var(--ds-accent-bg,var(--ds-accent-subtle))] text-[var(--ds-accent-text,var(--ds-text-primary))] border-[var(--ds-check-border)]" : "bg-[var(--ds-input-bg)] border-[var(--ds-input-border)] text-[var(--ds-text-primary)] hover:border-[var(--ds-input-border-hover)]"
|
|
2650
|
+
),
|
|
2651
|
+
children: weekdayName2(d, "short", locale)
|
|
2652
|
+
},
|
|
2653
|
+
d
|
|
2654
|
+
);
|
|
2655
|
+
}) }),
|
|
2656
|
+
shownDays && /* @__PURE__ */ jsx(InlineFieldError, { id: ids.daysError, message: shownDays, className: "mt-0" })
|
|
2657
|
+
] }),
|
|
2658
|
+
custom.freq === "monthly" && /* @__PURE__ */ jsx(
|
|
2659
|
+
RadioGroup,
|
|
2660
|
+
{
|
|
2661
|
+
label: "On",
|
|
2662
|
+
value: monthlyOn,
|
|
2663
|
+
onChange: (v) => {
|
|
2664
|
+
if (v === "last") edit({ day: -1, nth: void 0 });
|
|
2665
|
+
else if (v === "day") edit({ day: monthDay, nth: void 0 });
|
|
2666
|
+
else {
|
|
2667
|
+
const [, week, weekday2] = v.split(":").map(Number);
|
|
2668
|
+
edit({ nth: { week, weekday: weekday2 }, day: void 0 });
|
|
2669
|
+
}
|
|
2670
|
+
},
|
|
2671
|
+
options: [
|
|
2672
|
+
{ value: "day", label: `On day ${monthDay}` },
|
|
2673
|
+
...nths.map((n) => ({ value: nthId(n), label: `On the ${ORDINAL2[n.week]} ${weekdayName2(n.weekday, "long", locale)}` })),
|
|
2674
|
+
...start.getDate() === daysIn2(start) || custom.day === -1 ? [{ value: "last", label: "On the last day" }] : []
|
|
2675
|
+
]
|
|
2676
|
+
}
|
|
2677
|
+
),
|
|
2678
|
+
/* @__PURE__ */ jsx(
|
|
2679
|
+
RadioGroup,
|
|
2680
|
+
{
|
|
2681
|
+
label: "Ends",
|
|
2682
|
+
value: ends,
|
|
2683
|
+
onChange: (v) => {
|
|
2684
|
+
setUntilPending(false);
|
|
2685
|
+
if (v === "never") edit({ until: void 0, count: void 0 });
|
|
2686
|
+
else if (v === "until") edit({ count: void 0, until: endOfDay(new Date(start.getFullYear(), start.getMonth() + 1, start.getDate())) });
|
|
2687
|
+
else edit({ until: void 0, count: 10 });
|
|
2688
|
+
},
|
|
2689
|
+
options: [
|
|
2690
|
+
{ value: "never", label: "Never" },
|
|
2691
|
+
{
|
|
2692
|
+
value: "until",
|
|
2693
|
+
label: "On a date",
|
|
2694
|
+
reveal: /* @__PURE__ */ jsxs("div", { children: [
|
|
2695
|
+
/* @__PURE__ */ jsx(
|
|
2696
|
+
DatePicker,
|
|
2697
|
+
{
|
|
2698
|
+
label: "End date",
|
|
2699
|
+
size: "sm",
|
|
2700
|
+
value: custom.until ?? null,
|
|
2701
|
+
min: new Date(start.getFullYear(), start.getMonth(), start.getDate() + 1),
|
|
2702
|
+
onChange: (d) => {
|
|
2703
|
+
setUntilPending(!d);
|
|
2704
|
+
edit({ until: d ? endOfDay(d) : void 0 });
|
|
2705
|
+
},
|
|
2706
|
+
error: !!shownUntil,
|
|
2707
|
+
"aria-describedby": shownUntil ? ids.untilError : void 0
|
|
2708
|
+
}
|
|
2709
|
+
),
|
|
2710
|
+
shownUntil && /* @__PURE__ */ jsx(InlineFieldError, { id: ids.untilError, message: shownUntil })
|
|
2711
|
+
] })
|
|
2712
|
+
},
|
|
2713
|
+
{
|
|
2714
|
+
value: "count",
|
|
2715
|
+
label: "After a number of times",
|
|
2716
|
+
reveal: /* @__PURE__ */ jsxs("div", { className: "space-y-ds-1", children: [
|
|
2717
|
+
/* @__PURE__ */ jsx("label", { htmlFor: ids.count, className: "block text-sm font-medium text-[var(--ds-text-primary)]", children: "Number of times" }),
|
|
2718
|
+
/* @__PURE__ */ jsx(NumberInput, { id: ids.count, size: "sm", value: custom.count ?? 10, min: 1, max: 999, onChange: (n) => edit({ count: Math.max(1, n) }), className: "w-28" })
|
|
2719
|
+
] })
|
|
2720
|
+
}
|
|
2721
|
+
]
|
|
2722
|
+
}
|
|
2723
|
+
)
|
|
2724
|
+
] }) }),
|
|
2725
|
+
summary && /* @__PURE__ */ jsx("p", { id: ids.summary, className: "text-xs text-[var(--ds-text-secondary)]", children: summary })
|
|
2726
|
+
] });
|
|
2727
|
+
}
|
|
2728
|
+
var DEFAULT_BUTTON_ATTR = "data-dialog-default-button";
|
|
2729
|
+
var sizeClasses = {
|
|
2730
|
+
// round 16 (the owner's item 5): the small dialog is 448 px, not 384 — a delete confirmation with a typed field was cramped
|
|
2731
|
+
sm: "max-w-md",
|
|
2732
|
+
md: "max-w-lg",
|
|
2733
|
+
lg: "max-w-2xl",
|
|
2734
|
+
xl: "max-w-4xl",
|
|
2735
|
+
full: "max-w-[calc(100vw-2rem)]"
|
|
2736
|
+
};
|
|
2737
|
+
function Dialog({ open, onClose: onCloseProp, title, description, children, footer, variant = "default", size = "md", alert = false, container, onSubmit, dirty, onDiscard }) {
|
|
2738
|
+
const { marked, mark } = useOverlayMark(open);
|
|
2739
|
+
const guard = useDirtyGuard(dirty ?? marked, onCloseProp, onDiscard);
|
|
2740
|
+
const onClose = guard.requestClose;
|
|
2741
|
+
const titleId = useId();
|
|
2742
|
+
const descriptionId = useId();
|
|
2743
|
+
const isMobile = useBreakpoint("sm");
|
|
2744
|
+
const overlayRef = useRef(null);
|
|
2745
|
+
const dialogRef = useRef(null);
|
|
2746
|
+
const opener = useRef(null);
|
|
2747
|
+
const defaultButtonRef = useRef(null);
|
|
2748
|
+
const bodyRef = useScrollbarInset();
|
|
2749
|
+
const onCloseRef = useLatest(onClose);
|
|
2750
|
+
const onSubmitRef = useLatest(onSubmit);
|
|
2751
|
+
const isTopLayer = useOverlayLayer(open);
|
|
2752
|
+
useFocusTrap(dialogRef, open, isTopLayer);
|
|
2753
|
+
const before = useFocusBeforeOpen(open);
|
|
2754
|
+
useEffect(() => {
|
|
2755
|
+
if (!open) return;
|
|
2756
|
+
const active = before.current;
|
|
2757
|
+
opener.current = active instanceof HTMLElement && active !== document.body && active.isConnected ? rememberFocus(active) : null;
|
|
2758
|
+
}, [open, before]);
|
|
2759
|
+
useEffect(() => {
|
|
2760
|
+
if (!open) return;
|
|
2761
|
+
requestAnimationFrame(() => {
|
|
2762
|
+
focusInitial(dialogRef.current, { destructive: variant === "destructive" });
|
|
2763
|
+
});
|
|
2764
|
+
}, [open, variant]);
|
|
2765
|
+
useEffect(() => {
|
|
2766
|
+
if (!open) return;
|
|
2767
|
+
const handler = (e) => {
|
|
2768
|
+
if (e.key !== "Escape" || e.defaultPrevented || !isTopLayer()) return;
|
|
2769
|
+
e.preventDefault();
|
|
2770
|
+
onCloseRef.current();
|
|
2771
|
+
};
|
|
2772
|
+
document.addEventListener("keydown", handler);
|
|
2773
|
+
return () => {
|
|
2774
|
+
document.removeEventListener("keydown", handler);
|
|
2775
|
+
};
|
|
2776
|
+
}, [open, onCloseRef, isTopLayer]);
|
|
2777
|
+
useEffect(() => {
|
|
2778
|
+
if (!open) return;
|
|
2779
|
+
lockBodyScroll();
|
|
2780
|
+
return () => {
|
|
2781
|
+
unlockBodyScroll();
|
|
2782
|
+
const r = opener.current;
|
|
2783
|
+
opener.current = null;
|
|
2784
|
+
const active = document.activeElement;
|
|
2785
|
+
if (!active || active === document.body || !active.isConnected) r?.restore();
|
|
2786
|
+
};
|
|
2787
|
+
}, [open]);
|
|
2788
|
+
if (!open) return null;
|
|
2789
|
+
return createPortal(
|
|
2790
|
+
/* @__PURE__ */ jsxs(
|
|
2791
|
+
"div",
|
|
2792
|
+
{
|
|
2793
|
+
ref: overlayRef,
|
|
2794
|
+
className: cn("fixed inset-0 z-[var(--ds-z-modal)] flex items-center justify-center", !isMobile && "p-ds-4"),
|
|
2795
|
+
children: [
|
|
2796
|
+
/* @__PURE__ */ jsx(
|
|
2797
|
+
"div",
|
|
2798
|
+
{
|
|
2799
|
+
className: "fixed inset-0 bg-black/50 [backdrop-filter:blur(calc(var(--ds-glass-blur)*0.3))] [-webkit-backdrop-filter:blur(calc(var(--ds-glass-blur)*0.3))]",
|
|
2800
|
+
onClick: alert ? void 0 : onClose,
|
|
2801
|
+
"aria-hidden": "true"
|
|
2802
|
+
}
|
|
2803
|
+
),
|
|
2804
|
+
/* @__PURE__ */ jsxs(
|
|
2805
|
+
"form",
|
|
2806
|
+
{
|
|
2807
|
+
onSubmit: (e) => {
|
|
2808
|
+
if (e.target !== e.currentTarget) return;
|
|
2809
|
+
e.preventDefault();
|
|
2810
|
+
e.stopPropagation();
|
|
2811
|
+
if (variant === "destructive") return;
|
|
2812
|
+
const submitter = e.nativeEvent.submitter;
|
|
2813
|
+
const implicit = !submitter || submitter === defaultButtonRef.current;
|
|
2814
|
+
if (!implicit && submitter.getAttribute("type") !== "submit") return;
|
|
2815
|
+
if (implicit) {
|
|
2816
|
+
const explicit = e.currentTarget.querySelector(`button[type="submit"]:not([${DEFAULT_BUTTON_ATTR}])`);
|
|
2817
|
+
if (explicit?.disabled) return;
|
|
2818
|
+
}
|
|
2819
|
+
onSubmitRef.current?.();
|
|
2820
|
+
},
|
|
2821
|
+
className: "contents",
|
|
2822
|
+
children: [
|
|
2823
|
+
/* @__PURE__ */ jsx(
|
|
2824
|
+
"button",
|
|
2825
|
+
{
|
|
2826
|
+
ref: defaultButtonRef,
|
|
2827
|
+
type: "submit",
|
|
2828
|
+
tabIndex: -1,
|
|
2829
|
+
"aria-hidden": "true",
|
|
2830
|
+
className: "sr-only",
|
|
2831
|
+
...{ [DEFAULT_BUTTON_ATTR]: "" }
|
|
2832
|
+
}
|
|
2833
|
+
),
|
|
2834
|
+
/* @__PURE__ */ jsxs(
|
|
2835
|
+
"div",
|
|
2836
|
+
{
|
|
2837
|
+
ref: dialogRef,
|
|
2838
|
+
role: alert ? "alertdialog" : "dialog",
|
|
2839
|
+
...{ [OVERLAY_ROOT_ATTR]: "" },
|
|
2840
|
+
"aria-modal": "true",
|
|
2841
|
+
"data-gs": "dialog",
|
|
2842
|
+
"aria-labelledby": titleId,
|
|
2843
|
+
"aria-describedby": description ? descriptionId : void 0,
|
|
2844
|
+
style: { containerType: "inline-size", "--ds-form-max": "none" },
|
|
2845
|
+
className: cn(
|
|
2846
|
+
// a column: the title row, a body that scrolls when it is taller than the room, and the footer (Sprint 25.14,
|
|
2847
|
+
// with A36's full-screen phone dialog: its content ran past the screen with the footer cut off)
|
|
2848
|
+
"relative z-10 w-full flex flex-col max-h-full",
|
|
2849
|
+
isMobile ? "max-w-none h-full" : sizeClasses[size],
|
|
2850
|
+
OVERLAY_SURFACE,
|
|
2851
|
+
"text-[var(--ds-text-primary)]",
|
|
2852
|
+
GLASS_OVERLAY,
|
|
2853
|
+
// full screen on a phone: no edge to draw, so the content sits at the gutter from the screen's edge
|
|
2854
|
+
isMobile ? "rounded-none" : "rounded-[var(--ds-radius-xl)] border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
2855
|
+
"overflow-hidden",
|
|
2856
|
+
"animate-in fade-in-0 zoom-in-95"
|
|
2857
|
+
),
|
|
2858
|
+
children: [
|
|
2859
|
+
/* @__PURE__ */ jsxs("div", { className: cn("shrink-0 flex items-start gap-ds-3 pt-ds-6 px-[var(--ds-page-gutter)]", children ? "pb-ds-4" : "pb-ds-6"), children: [
|
|
2860
|
+
variant === "destructive" && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center shrink-0 w-10 h-10 rounded-[var(--ds-radius-full)] bg-[var(--ds-status-error-bg)]", children: /* @__PURE__ */ jsx(Icon, { name: "warning", size: 20, className: "text-[var(--ds-status-error)]" }) }),
|
|
2861
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
2862
|
+
/* @__PURE__ */ jsx(
|
|
2863
|
+
"h2",
|
|
2864
|
+
{
|
|
2865
|
+
id: titleId,
|
|
2866
|
+
className: "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] leading-none tracking-tight",
|
|
2867
|
+
children: title
|
|
2868
|
+
}
|
|
2869
|
+
),
|
|
2870
|
+
description && /* @__PURE__ */ jsx("p", { id: descriptionId, className: "mt-ds-2 text-sm text-[var(--ds-text-muted)]", children: description })
|
|
2871
|
+
] }),
|
|
2872
|
+
/* @__PURE__ */ jsx(
|
|
2873
|
+
"button",
|
|
2874
|
+
{
|
|
2875
|
+
type: "button",
|
|
2876
|
+
onClick: onClose,
|
|
2877
|
+
...{ [OVERLAY_CLOSE_ATTR]: "" },
|
|
2878
|
+
className: "shrink-0 text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer",
|
|
2879
|
+
"aria-label": "Close",
|
|
2880
|
+
children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 18 })
|
|
2881
|
+
}
|
|
2882
|
+
)
|
|
2883
|
+
] }),
|
|
2884
|
+
children && /* @__PURE__ */ jsx(
|
|
2885
|
+
"div",
|
|
2886
|
+
{
|
|
2887
|
+
ref: bodyRef,
|
|
2888
|
+
className: "min-h-0 flex-[0_1_auto] overflow-y-auto pb-ds-6",
|
|
2889
|
+
style: {
|
|
2890
|
+
paddingLeft: variant === "destructive" ? "calc(var(--ds-page-gutter) + 2.5rem + var(--ds-space-3))" : "var(--ds-page-gutter)",
|
|
2891
|
+
paddingRight: insetLessScrollbar("var(--ds-page-gutter)")
|
|
2892
|
+
},
|
|
2893
|
+
children: /* @__PURE__ */ jsx(SurfaceBoundary, { children: /* @__PURE__ */ jsx(DrawerFooterCtx, { value: null, children: /* @__PURE__ */ jsx(OverlayMarkScope, { mark, children: /* @__PURE__ */ jsx(OverlayCloseCtx, { value: onClose, children }) }) }) })
|
|
2894
|
+
}
|
|
2895
|
+
),
|
|
2896
|
+
isMobile && /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "flex-1 min-h-0" }),
|
|
2897
|
+
/* @__PURE__ */ jsx(DiscardConfirm, { open: guard.confirming, onKeep: guard.keep, onDiscard: guard.discard }),
|
|
2898
|
+
footer && /* @__PURE__ */ jsx("div", { className: cn(
|
|
2899
|
+
"shrink-0 flex justify-end gap-ds-2 py-ds-4 px-[var(--ds-page-gutter)]",
|
|
2900
|
+
"border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
2901
|
+
"bg-[var(--ds-bg-muted)]",
|
|
2902
|
+
!isMobile && "rounded-b-[var(--ds-radius-xl)]"
|
|
2903
|
+
), children: footer })
|
|
2904
|
+
]
|
|
2905
|
+
}
|
|
2906
|
+
)
|
|
2907
|
+
]
|
|
2908
|
+
}
|
|
2909
|
+
)
|
|
1827
2910
|
]
|
|
1828
2911
|
}
|
|
1829
2912
|
),
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
const between = inRange(d);
|
|
1868
|
-
const dis = isDisabledDay(d);
|
|
1869
|
-
return /* @__PURE__ */ jsx(
|
|
1870
|
-
"button",
|
|
1871
|
-
{
|
|
1872
|
-
type: "button",
|
|
1873
|
-
role: "gridcell",
|
|
1874
|
-
"data-grid-key": dayKey(d),
|
|
1875
|
-
tabIndex: grid.tabIndexOf(d),
|
|
1876
|
-
"aria-disabled": dis || void 0,
|
|
1877
|
-
onClick: () => selectDay(d),
|
|
1878
|
-
onFocus: () => {
|
|
1879
|
-
if (!isSameDay(d, focusDate)) setFocusDate(d);
|
|
1880
|
-
},
|
|
1881
|
-
onMouseEnter: () => setHover(d),
|
|
1882
|
-
"aria-selected": isStart || isEnd || between,
|
|
1883
|
-
"aria-current": isSameDay(d, today) ? "date" : void 0,
|
|
1884
|
-
"aria-label": formatDayLong(d),
|
|
1885
|
-
className: cn(
|
|
1886
|
-
"w-full aspect-square flex items-center justify-center text-xs",
|
|
1887
|
-
"transition-colors cursor-pointer",
|
|
1888
|
-
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
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)]",
|
|
1890
|
-
dis && "opacity-disabled cursor-not-allowed hover:bg-transparent"
|
|
1891
|
-
),
|
|
1892
|
-
children: d.getDate()
|
|
1893
|
-
},
|
|
1894
|
-
d.toISOString()
|
|
1895
|
-
);
|
|
1896
|
-
}) }, w))
|
|
1897
|
-
] }, `${m.getFullYear()}-${m.getMonth()}`)) }),
|
|
1898
|
-
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center bg-[var(--ds-bg-muted)] border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] rounded-br-[var(--ds-radius-md)] px-ds-3 py-ds-2", children: [
|
|
1899
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--ds-text-muted)]", children: value.start && !value.end ? "Now pick an end date" : summary ?? "Pick a start date" }),
|
|
1900
|
-
(value.start || value.end) && /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => {
|
|
1901
|
-
onChange({ start: null, end: null });
|
|
1902
|
-
setHover(null);
|
|
1903
|
-
}, children: "Clear" })
|
|
1904
|
-
] })
|
|
1905
|
-
] })
|
|
1906
|
-
]
|
|
1907
|
-
}
|
|
1908
|
-
),
|
|
1909
|
-
container ?? document.body
|
|
1910
|
-
)
|
|
1911
|
-
] });
|
|
2913
|
+
container ?? document.body
|
|
2914
|
+
);
|
|
2915
|
+
}
|
|
2916
|
+
var SCOPES = [
|
|
2917
|
+
{ value: "this", label: "This event" },
|
|
2918
|
+
{ value: "following", label: "This and following events" },
|
|
2919
|
+
{ value: "all", label: "All events" }
|
|
2920
|
+
];
|
|
2921
|
+
function RecurrenceScopeDialog({ open, title, verb, destructive = false, repeatChanged: repeatChanged2 = false, edited, onChoose, onCancel }) {
|
|
2922
|
+
const first = repeatChanged2 ? "following" : "this";
|
|
2923
|
+
const [scope, setScope] = useState(first);
|
|
2924
|
+
const [wasOpen, setWasOpen] = useState(open);
|
|
2925
|
+
if (open !== wasOpen) {
|
|
2926
|
+
setWasOpen(open);
|
|
2927
|
+
if (open) setScope(first);
|
|
2928
|
+
}
|
|
2929
|
+
const chosen = repeatChanged2 && scope === "this" ? first : scope;
|
|
2930
|
+
const noteId = useId();
|
|
2931
|
+
const undone = repeatChanged2 && chosen !== "this" ? edited?.[chosen] ?? 0 : 0;
|
|
2932
|
+
return /* @__PURE__ */ jsxs(
|
|
2933
|
+
Dialog,
|
|
2934
|
+
{
|
|
2935
|
+
open,
|
|
2936
|
+
onClose: onCancel,
|
|
2937
|
+
title,
|
|
2938
|
+
size: "sm",
|
|
2939
|
+
variant: destructive ? "destructive" : "default",
|
|
2940
|
+
footer: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2941
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", onClick: onCancel, children: "Cancel" }),
|
|
2942
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: destructive ? "destructive" : "default", onClick: () => onChoose(chosen), children: verb })
|
|
2943
|
+
] }),
|
|
2944
|
+
children: [
|
|
2945
|
+
/* @__PURE__ */ jsx(RadioGroup, { label: "Apply to", value: chosen, onChange: (v) => setScope(v), options: repeatChanged2 ? SCOPES.slice(1) : SCOPES, "aria-describedby": undone > 0 ? noteId : void 0 }),
|
|
2946
|
+
undone > 0 && /* @__PURE__ */ jsx("p", { id: noteId, className: "mt-ds-3 text-sm text-[var(--ds-text-secondary)]", children: undone === 1 ? "1 of these events was changed on its own. Changing how it repeats undoes its changes." : `${undone} of these events were changed on their own. Changing how it repeats undoes their changes.` })
|
|
2947
|
+
]
|
|
2948
|
+
}
|
|
2949
|
+
);
|
|
1912
2950
|
}
|
|
1913
2951
|
|
|
1914
2952
|
// ../../showcase/src/lib/file-accept.ts
|
|
@@ -1952,12 +2990,12 @@ function fileFormat(file) {
|
|
|
1952
2990
|
function matches(file, tokens) {
|
|
1953
2991
|
if (tokens.length === 0 || tokens.some((t) => t.kind === "any")) return true;
|
|
1954
2992
|
const name = file.name.toLowerCase();
|
|
1955
|
-
const
|
|
2993
|
+
const format3 = fileFormat(file);
|
|
1956
2994
|
const type = file.type.toLowerCase();
|
|
1957
2995
|
return tokens.some((t) => {
|
|
1958
2996
|
if (t.kind === "family") return type === "" || type.startsWith(`${t.family}/`);
|
|
1959
2997
|
if (t.kind !== "format") return false;
|
|
1960
|
-
return t.name ===
|
|
2998
|
+
return t.name === format3 || t.suffix != null && name.endsWith(t.suffix) || t.mime != null && t.mime === type;
|
|
1961
2999
|
});
|
|
1962
3000
|
}
|
|
1963
3001
|
var joinOr = (items) => items.length < 2 ? items.join("") : `${items.slice(0, -1).join(", ")} or ${items[items.length - 1]}`;
|
|
@@ -1969,9 +3007,9 @@ function typeWords(accept) {
|
|
|
1969
3007
|
const tokens = parseAccept(accept);
|
|
1970
3008
|
if (tokens.length === 0 || tokens.some((t) => t.kind === "any" || t.kind === "family" && !FAMILIES[t.family])) return null;
|
|
1971
3009
|
const families = [...new Set(tokens.flatMap((t) => t.kind === "family" ? [t.family] : []))].map((f) => FAMILIES[f]);
|
|
1972
|
-
const
|
|
1973
|
-
const many = `${joinOr([...families.map((f) => f.many), ...
|
|
1974
|
-
const one = families.length === 0 ? `${article(
|
|
3010
|
+
const formats3 = [...new Set(tokens.flatMap((t) => t.kind === "format" ? [t.name] : []))];
|
|
3011
|
+
const many = `${joinOr([...families.map((f) => f.many), ...formats3])}${formats3.length ? " files" : ""}`;
|
|
3012
|
+
const one = families.length === 0 ? `${article(formats3[0])} ${joinOr(formats3)}` : joinOr([...families.map((f) => f.one), ...formats3.map((f) => `${article(f)} ${f}`)]);
|
|
1975
3013
|
return { one, many };
|
|
1976
3014
|
}
|
|
1977
3015
|
function sizeWords(bytes) {
|
|
@@ -2198,10 +3236,10 @@ function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accep
|
|
|
2198
3236
|
focusAfterRemoval(rows, gone.index, inputRef.current);
|
|
2199
3237
|
return;
|
|
2200
3238
|
}
|
|
2201
|
-
const
|
|
3239
|
+
const last2 = lastAction.current;
|
|
2202
3240
|
const active = document.activeElement;
|
|
2203
|
-
if (!
|
|
2204
|
-
const row = Array.from(listRef.current?.querySelectorAll(":scope > li") ?? []).find((li) => li.dataset.uploadId ===
|
|
3241
|
+
if (!last2 || last2.el.isConnected || active && active !== document.body) return;
|
|
3242
|
+
const row = Array.from(listRef.current?.querySelectorAll(":scope > li") ?? []).find((li) => li.dataset.uploadId === last2.id);
|
|
2205
3243
|
row?.querySelector("button")?.focus();
|
|
2206
3244
|
}, [shown]);
|
|
2207
3245
|
const addFiles = useCallback(
|
|
@@ -2526,7 +3564,7 @@ var TEXT_SIZE4 = {
|
|
|
2526
3564
|
md: "text-sm",
|
|
2527
3565
|
lg: "text-base"
|
|
2528
3566
|
};
|
|
2529
|
-
function
|
|
3567
|
+
function pad3(n) {
|
|
2530
3568
|
return n.toString().padStart(2, "0");
|
|
2531
3569
|
}
|
|
2532
3570
|
function generateHours(use24) {
|
|
@@ -2602,7 +3640,7 @@ function TimePicker({
|
|
|
2602
3640
|
setPrevOpen(open);
|
|
2603
3641
|
if (open) setColumnStop({});
|
|
2604
3642
|
}
|
|
2605
|
-
const
|
|
3643
|
+
const stopOf2 = (column, chosen) => columnStop[column] ?? Math.max(0, chosen);
|
|
2606
3644
|
const holdStop = (column, index) => setColumnStop((s) => s[column] === index ? s : { ...s, [column]: index });
|
|
2607
3645
|
const chosenHour = hours.findIndex((h) => use24Hour ? h === parseInt(value) : h === parsed.hour);
|
|
2608
3646
|
const chosenMinute = minutes.findIndex((m) => m === parsed.minute);
|
|
@@ -2641,7 +3679,7 @@ function TimePicker({
|
|
|
2641
3679
|
if (period === "AM" && hour === 12) h24 = 0;
|
|
2642
3680
|
else if (period === "PM" && hour !== 12) h24 = hour + 12;
|
|
2643
3681
|
}
|
|
2644
|
-
onChange(`${
|
|
3682
|
+
onChange(`${pad3(h24)}:${pad3(minute)}`);
|
|
2645
3683
|
}
|
|
2646
3684
|
const specs = timeSegments(use24Hour);
|
|
2647
3685
|
const [segs, setSegs] = useState(() => fromValue(value, use24Hour));
|
|
@@ -2688,10 +3726,10 @@ function TimePicker({
|
|
|
2688
3726
|
lastCommitted.current = out;
|
|
2689
3727
|
if (out !== value) onChange(out);
|
|
2690
3728
|
};
|
|
2691
|
-
const setSegment = (key, v,
|
|
3729
|
+
const setSegment = (key, v, commit2 = true) => {
|
|
2692
3730
|
setSegs((s) => {
|
|
2693
3731
|
const next = { ...s, [key]: v };
|
|
2694
|
-
if (
|
|
3732
|
+
if (commit2) commitIfComplete(next);
|
|
2695
3733
|
return next;
|
|
2696
3734
|
});
|
|
2697
3735
|
};
|
|
@@ -2893,7 +3931,7 @@ function TimePicker({
|
|
|
2893
3931
|
"button",
|
|
2894
3932
|
{
|
|
2895
3933
|
type: "button",
|
|
2896
|
-
tabIndex: i ===
|
|
3934
|
+
tabIndex: i === stopOf2("hour", chosenHour) ? 0 : -1,
|
|
2897
3935
|
onFocus: () => holdStop("hour", i),
|
|
2898
3936
|
"data-selected": use24Hour ? h === parseInt(value) : h === parsed.hour,
|
|
2899
3937
|
onMouseDown: (e) => e.preventDefault(),
|
|
@@ -2903,7 +3941,7 @@ function TimePicker({
|
|
|
2903
3941
|
"transition-colors focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
2904
3942
|
(use24Hour ? h === parseInt(value) : h === parsed.hour) ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]" : "text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-emphasis)]"
|
|
2905
3943
|
),
|
|
2906
|
-
children:
|
|
3944
|
+
children: pad3(h)
|
|
2907
3945
|
},
|
|
2908
3946
|
h
|
|
2909
3947
|
)) }),
|
|
@@ -2912,7 +3950,7 @@ function TimePicker({
|
|
|
2912
3950
|
"button",
|
|
2913
3951
|
{
|
|
2914
3952
|
type: "button",
|
|
2915
|
-
tabIndex: i ===
|
|
3953
|
+
tabIndex: i === stopOf2("minute", chosenMinute) ? 0 : -1,
|
|
2916
3954
|
onFocus: () => holdStop("minute", i),
|
|
2917
3955
|
"data-selected": m === parsed.minute,
|
|
2918
3956
|
onMouseDown: (e) => e.preventDefault(),
|
|
@@ -2922,7 +3960,7 @@ function TimePicker({
|
|
|
2922
3960
|
"transition-colors focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
2923
3961
|
m === parsed.minute ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]" : "text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-emphasis)]"
|
|
2924
3962
|
),
|
|
2925
|
-
children:
|
|
3963
|
+
children: pad3(m)
|
|
2926
3964
|
},
|
|
2927
3965
|
m
|
|
2928
3966
|
)) }),
|
|
@@ -2932,7 +3970,7 @@ function TimePicker({
|
|
|
2932
3970
|
"button",
|
|
2933
3971
|
{
|
|
2934
3972
|
type: "button",
|
|
2935
|
-
tabIndex: i ===
|
|
3973
|
+
tabIndex: i === stopOf2("period", chosenPeriod) ? 0 : -1,
|
|
2936
3974
|
onFocus: () => holdStop("period", i),
|
|
2937
3975
|
"data-selected": p === parsed.period,
|
|
2938
3976
|
onMouseDown: (e) => e.preventDefault(),
|
|
@@ -4069,14 +5107,16 @@ function AddAnother({ items, getId, itemName, columns, renderRow, onAdd, onRemov
|
|
|
4069
5107
|
const body = /* @__PURE__ */ jsxs("div", { "data-add-another": "", className: cn("@container flex flex-col gap-ds-3", className), style: grid, children: [
|
|
4070
5108
|
/* @__PURE__ */ jsxs("div", { "aria-hidden": "true", className: "hidden gap-ds-3 text-sm font-medium text-[var(--ds-text-secondary)] @min-[30rem]:grid @min-[30rem]:grid-cols-[var(--gs-add-another-cols)]", children: [
|
|
4071
5109
|
columns.map((column) => /* @__PURE__ */ jsx("span", { children: column }, column)),
|
|
4072
|
-
canRemove && /* @__PURE__ */ jsx("span", { className: "invisible inline-flex items-center whitespace-nowrap
|
|
5110
|
+
canRemove && /* @__PURE__ */ jsx("span", { className: "invisible inline-flex items-center whitespace-nowrap text-xs font-medium", children: "Remove" })
|
|
4073
5111
|
] }),
|
|
4074
5112
|
/* @__PURE__ */ jsx("ul", { ref: listRef, className: "flex flex-col gap-ds-4 @min-[30rem]:gap-ds-3", children: items.map((item, index) => {
|
|
4075
5113
|
const id = getId(item);
|
|
4076
5114
|
return /* @__PURE__ */ jsxs("li", { "data-add-another-row": "", className: "grid grid-cols-1 items-start gap-ds-3 @min-[30rem]:grid-cols-[var(--gs-add-another-cols)]", children: [
|
|
4077
5115
|
/* @__PURE__ */ jsx(AddAnotherRowCtx.Provider, { value: true, children: renderRow(item, index, (column) => `${column}, ${itemName(index)}`) }),
|
|
4078
|
-
canRemove && // the visible "Remove" starts its name, which says whose row it removes (WCAG 2.5.3 label in name)
|
|
4079
|
-
|
|
5116
|
+
canRemove && // the visible "Remove" starts its name, which says whose row it removes (WCAG 2.5.3 label in name). A
|
|
5117
|
+
// link, alone under or beside its fields (Sprint 25.19 G4, page_composition#51): its word lines up with
|
|
5118
|
+
// the fields' edge, and beside them it takes a field's height, so it sits on their middle
|
|
5119
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "link", size: "sm", "aria-label": `Remove ${itemName(index)}`, className: "justify-self-start @min-[30rem]:h-[var(--ds-control-height-md)]", onClick: () => {
|
|
4080
5120
|
pending.current = { kind: "remove", id, index };
|
|
4081
5121
|
reportChange?.();
|
|
4082
5122
|
onRemove(id);
|
|
@@ -4531,7 +5571,7 @@ function holdsHeader(children) {
|
|
|
4531
5571
|
Children.forEach(children, (child) => {
|
|
4532
5572
|
if (found || !isValidElement(child)) return;
|
|
4533
5573
|
if (child.type === Fragment$1) found = holdsHeader(child.props.children);
|
|
4534
|
-
else if (child.type === CardHeader) found = true;
|
|
5574
|
+
else if (elementType(child.type) === CardHeader) found = true;
|
|
4535
5575
|
});
|
|
4536
5576
|
return found;
|
|
4537
5577
|
}
|
|
@@ -4847,7 +5887,7 @@ function partsOf(children) {
|
|
|
4847
5887
|
}
|
|
4848
5888
|
function splitTitle(children) {
|
|
4849
5889
|
const parts = partsOf(children);
|
|
4850
|
-
const at = parts.findIndex((p) => isValidElement(p) && p.type === CardTitle);
|
|
5890
|
+
const at = parts.findIndex((p) => isValidElement(p) && elementType(p.type) === CardTitle);
|
|
4851
5891
|
if (at < 0) return { lead: [], title: parts[0] ?? null, rest: parts.slice(1) };
|
|
4852
5892
|
return { lead: parts.slice(0, at), title: parts[at], rest: parts.slice(at + 1) };
|
|
4853
5893
|
}
|
|
@@ -4896,7 +5936,7 @@ var CardHeader = forwardRef(function CardHeader2(allProps, ref) {
|
|
|
4896
5936
|
const { lead, title, rest } = splitTitle(children);
|
|
4897
5937
|
const leadBlock = lead.length > 0 ? /* @__PURE__ */ jsx("div", { "data-card-lead": "", className: "flex flex-col space-y-ds-1.5 min-w-0 grow", children: lead }) : null;
|
|
4898
5938
|
const topLine = iconBlock ?? leadBlock;
|
|
4899
|
-
const ownBlock = title !== null && !(isValidElement(title) && title.type === CardTitle);
|
|
5939
|
+
const ownBlock = title !== null && !(isValidElement(title) && elementType(title.type) === CardTitle);
|
|
4900
5940
|
const actionsSlot = "actions" in allProps ? /* @__PURE__ */ jsx("div", { "data-header-actions": "", className: "contents", children: partsOf(actions).map((item, i) => /* @__PURE__ */ jsx("span", { className: cn("flex items-center shrink-0", TITLE_LINE), children: item }, isValidElement(item) && item.key !== null ? item.key : i)) }) : null;
|
|
4901
5941
|
return /* @__PURE__ */ jsxs("div", { ref, "data-card-header": "", className: cn("flex flex-col px-ds-5 pt-ds-4 last:pb-ds-4 min-w-0", className), ...props, children: [
|
|
4902
5942
|
topLine && /* @__PURE__ */ jsxs("div", { "data-card-icon-row": iconBlock ? "" : void 0, "data-card-lead-row": iconBlock ? void 0 : "", className: cn("flex items-start gap-ds-2", iconBlock ? "mb-ds-2.5" : "mb-ds-1.5"), children: [
|
|
@@ -5489,7 +6529,7 @@ function useTitleFloorFits(rowRef, active) {
|
|
|
5489
6529
|
}
|
|
5490
6530
|
function actionsAreBadges(actions) {
|
|
5491
6531
|
const items = Children.toArray(actions);
|
|
5492
|
-
return items.length > 0 && items.every((item) => isValidElement(item) && (item.type === Fragment$1 ? actionsAreBadges(item.props.children) : item.type === Badge));
|
|
6532
|
+
return items.length > 0 && items.every((item) => isValidElement(item) && (item.type === Fragment$1 ? actionsAreBadges(item.props.children) : elementType(item.type) === Badge));
|
|
5493
6533
|
}
|
|
5494
6534
|
function TruncCell({ children, lines }) {
|
|
5495
6535
|
const { ref, isTruncated } = useTextOverflow({ lines });
|
|
@@ -5536,19 +6576,13 @@ function sortableValue(v) {
|
|
|
5536
6576
|
if (typeof v === "boolean") return v ? 1 : 0;
|
|
5537
6577
|
return isValidElement(v) || typeof v === "object" ? null : String(v);
|
|
5538
6578
|
}
|
|
5539
|
-
var COLLATORS =
|
|
5540
|
-
function collator() {
|
|
5541
|
-
|
|
5542
|
-
let c = COLLATORS.get(locale);
|
|
5543
|
-
if (!c) {
|
|
5544
|
-
c = new Intl.Collator(locale || void 0, { numeric: true });
|
|
5545
|
-
COLLATORS.set(locale, c);
|
|
5546
|
-
}
|
|
5547
|
-
return c;
|
|
6579
|
+
var COLLATORS = localeCache(32);
|
|
6580
|
+
function collator(given) {
|
|
6581
|
+
return COLLATORS(given ?? "", () => new Intl.Collator(given || void 0, { numeric: true }));
|
|
5548
6582
|
}
|
|
5549
|
-
function compareValues(a, b) {
|
|
6583
|
+
function compareValues(a, b, locale) {
|
|
5550
6584
|
if (typeof a === "number" && typeof b === "number") return a - b;
|
|
5551
|
-
return collator().compare(String(a), String(b));
|
|
6585
|
+
return collator(locale).compare(String(a), String(b));
|
|
5552
6586
|
}
|
|
5553
6587
|
var UNIT_SCALE = {
|
|
5554
6588
|
"": 1,
|
|
@@ -5710,12 +6744,13 @@ function Table({
|
|
|
5710
6744
|
);
|
|
5711
6745
|
const columnKeys = useMemo(() => columns.map((c) => c.key), [columns]);
|
|
5712
6746
|
const inferredKinds = useMemo(() => inferColumnKinds(data, columnKeys), [data, columnKeys]);
|
|
5713
|
-
const
|
|
6747
|
+
const kindOf2 = useCallback(
|
|
5714
6748
|
(col) => col.kind ?? inferredKinds.get(col.key),
|
|
5715
6749
|
[inferredKinds]
|
|
5716
6750
|
);
|
|
5717
6751
|
const sortColumn = sortKey ? columns.find((c) => c.key === sortKey) : void 0;
|
|
5718
|
-
const sortKind = sortColumn ?
|
|
6752
|
+
const sortKind = sortColumn ? kindOf2(sortColumn) : void 0;
|
|
6753
|
+
const locale = useFormatLocale();
|
|
5719
6754
|
const { sortedAll, unsortable } = useMemo(() => {
|
|
5720
6755
|
const indexed = data.map((row, i) => ({ row, originalIdx: i }));
|
|
5721
6756
|
if (!sortKey || !sortDir) return { sortedAll: indexed, unsortable: null };
|
|
@@ -5729,11 +6764,11 @@ function Table({
|
|
|
5729
6764
|
const elements = valued.some((v) => v.value === null);
|
|
5730
6765
|
const sorted = elements ? indexed : valued.sort((a, b) => {
|
|
5731
6766
|
if (a.value === void 0 || b.value === void 0) return a.value === b.value ? 0 : a.value === void 0 ? 1 : -1;
|
|
5732
|
-
const cmp = compareValues(a.value, b.value);
|
|
6767
|
+
const cmp = compareValues(a.value, b.value, locale);
|
|
5733
6768
|
return sortDir === "asc" ? cmp : -cmp;
|
|
5734
6769
|
});
|
|
5735
6770
|
return { sortedAll: sorted, unsortable: elements ? sortKey : null };
|
|
5736
|
-
}, [data, sortKey, sortDir, sortColumn, sortKind]);
|
|
6771
|
+
}, [data, sortKey, sortDir, sortColumn, sortKind, locale]);
|
|
5737
6772
|
const canSort = useMemo(() => {
|
|
5738
6773
|
const can = /* @__PURE__ */ new Set();
|
|
5739
6774
|
for (const col of columns) if (col.sortValue || data.every((row) => sortableValue(row[col.key]) !== null)) can.add(col.key);
|
|
@@ -5828,8 +6863,8 @@ function Table({
|
|
|
5828
6863
|
const frame = scroller.clientWidth;
|
|
5829
6864
|
const nameFits = nameIndex >= 0 && frame > 0 && at + nameWidth + fromRight <= frame / 2;
|
|
5830
6865
|
if (nameFits) start.push(at);
|
|
5831
|
-
const
|
|
5832
|
-
const panel = cells.length > lead ? [at +
|
|
6866
|
+
const pad4 = (cell, side) => cell ? parseFloat(getComputedStyle(cell)[side]) || 0 : 0;
|
|
6867
|
+
const panel = cells.length > lead ? [at + pad4(cells[lead], "paddingLeft"), pad4(cells[cells.length - 1], "paddingRight")] : null;
|
|
5833
6868
|
const next = { start, end, nameFits, frame, panel };
|
|
5834
6869
|
setPins((prev) => samePins(prev, next) ? prev : next);
|
|
5835
6870
|
};
|
|
@@ -5860,13 +6895,13 @@ function Table({
|
|
|
5860
6895
|
if (!table2 || isMobile) return;
|
|
5861
6896
|
const next = /* @__PURE__ */ new Map();
|
|
5862
6897
|
for (const col of columns) {
|
|
5863
|
-
if (
|
|
6898
|
+
if (kindOf2(col)) continue;
|
|
5864
6899
|
const texts = Array.from(table2.querySelectorAll(`:scope > tbody > tr > td[data-col="${CSS.escape(col.key)}"]`)).slice(0, 50).map((td) => td.textContent ?? "");
|
|
5865
6900
|
const kind = texts.length ? kindOfRenderedText(texts) : void 0;
|
|
5866
6901
|
if (kind) next.set(col.key, kind);
|
|
5867
6902
|
}
|
|
5868
6903
|
setRenderedKinds((prev) => prev.size === next.size && [...next].every(([k, v]) => prev.get(k) === v) ? prev : next);
|
|
5869
|
-
}, [columns,
|
|
6904
|
+
}, [columns, kindOf2, drawn, isMobile]);
|
|
5870
6905
|
const expandedKey = expanded.map(String).join("");
|
|
5871
6906
|
const shownBefore = useRef(/* @__PURE__ */ new Set());
|
|
5872
6907
|
const pendingScroll = useRef(null);
|
|
@@ -5913,10 +6948,10 @@ function Table({
|
|
|
5913
6948
|
const control = pager && !loading && data.length > 0 ? /* @__PURE__ */ jsx(Pagination, { ...pager.props }) : null;
|
|
5914
6949
|
const listRoot = control ? void 0 : setRoot;
|
|
5915
6950
|
const listClass = control ? void 0 : className;
|
|
5916
|
-
const withControl = (
|
|
5917
|
-
|
|
6951
|
+
const withControl = (list2) => control ? /* @__PURE__ */ jsxs("div", { ref: setRoot, "data-gs-paged": "", className: cn("flex flex-col min-w-0", className), children: [
|
|
6952
|
+
list2,
|
|
5918
6953
|
control
|
|
5919
|
-
] }) :
|
|
6954
|
+
] }) : list2;
|
|
5920
6955
|
const focusWas = useRef(null);
|
|
5921
6956
|
const noteFocus = (e) => {
|
|
5922
6957
|
const target = e.target;
|
|
@@ -6055,7 +7090,7 @@ function Table({
|
|
|
6055
7090
|
columns.map((col, c) => {
|
|
6056
7091
|
const isSortable = col.header.trim() !== "" && (col.sortable ?? (!!sortable && canSort.has(col.key)));
|
|
6057
7092
|
const isActiveSort = sortKey === col.key && !!sortDir && unsortable !== col.key;
|
|
6058
|
-
const headerKind =
|
|
7093
|
+
const headerKind = kindOf2(col);
|
|
6059
7094
|
const headerAlign = col.align ?? (headerKind === "number" ? "right" : "left");
|
|
6060
7095
|
const shrink = (headerKind === "number" || headerKind === "date") && !col.maxWidth;
|
|
6061
7096
|
const style = { maxWidth: col.maxWidth, width: col.width, minWidth: col.minWidth, ...pinStyle(lead + c, cellCount) };
|
|
@@ -6177,11 +7212,11 @@ function Table({
|
|
|
6177
7212
|
) }),
|
|
6178
7213
|
columns.map((col, c) => {
|
|
6179
7214
|
const truncLines = col.truncate === true ? 1 : col.truncate ? col.truncate.lines : 0;
|
|
6180
|
-
const kind =
|
|
7215
|
+
const kind = kindOf2(col);
|
|
6181
7216
|
const alignClass = col.align ? col.align === "right" ? "text-right" : col.align === "center" ? "text-center" : "text-left" : kind === "number" ? "text-right" : "text-left";
|
|
6182
7217
|
const cellContent = row[col.key];
|
|
6183
7218
|
const shrink = (kind === "number" || kind === "date") && !col.maxWidth;
|
|
6184
|
-
const
|
|
7219
|
+
const whole2 = !kind && renderedKinds.has(col.key);
|
|
6185
7220
|
let inner;
|
|
6186
7221
|
if (truncLines > 0) {
|
|
6187
7222
|
inner = /* @__PURE__ */ jsx(TruncCell, { lines: truncLines, children: cellContent });
|
|
@@ -6204,7 +7239,7 @@ function Table({
|
|
|
6204
7239
|
"text-[var(--ds-text-primary)]",
|
|
6205
7240
|
alignClass,
|
|
6206
7241
|
shrink && "w-px whitespace-nowrap",
|
|
6207
|
-
|
|
7242
|
+
whole2 && "whitespace-nowrap",
|
|
6208
7243
|
kind === "identifier" && "[overflow-wrap:anywhere]"
|
|
6209
7244
|
),
|
|
6210
7245
|
style: col.maxWidth || col.width || col.minWidth || c + lead < pinnedStart || c >= columns.length - endCount ? { maxWidth: col.maxWidth, width: col.width, minWidth: col.minWidth, ...pinStyle(lead + c, cellCount) } : void 0,
|
|
@@ -6444,7 +7479,7 @@ function SegmentedControl({
|
|
|
6444
7479
|
// theme's radius; the segments inside sit concentric with it (SEGMENT_RADIUS)
|
|
6445
7480
|
"rounded-[var(--ds-radius-md)]",
|
|
6446
7481
|
// The frame's edge is a button's: each segment is a labelled button, so the frame isn't what identifies the
|
|
6447
|
-
// control, and WCAG 1.4.11 asks no 3:1 of it
|
|
7482
|
+
// control, and WCAG 1.4.11 asks no 3:1 of it
|
|
6448
7483
|
variant === "default" && "border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
6449
7484
|
control.invalid && "border-[length:var(--ds-border-width)] border-[var(--ds-status-error)]",
|
|
6450
7485
|
className
|
|
@@ -6457,9 +7492,11 @@ function SegmentedControl({
|
|
|
6457
7492
|
className: cn(
|
|
6458
7493
|
"absolute rounded-[var(--ds-segment-radius)]",
|
|
6459
7494
|
"bg-[var(--ds-bg-surface)]",
|
|
6460
|
-
// The selected
|
|
6461
|
-
//
|
|
6462
|
-
|
|
7495
|
+
// The selected segment is a kind of button, so it takes a secondary button's surface and edge, as the frame
|
|
7496
|
+
// takes a button's edge (the owner, 3 October 2026: the 3:1 strong edge it kept from Sprint 25.14 drew the
|
|
7497
|
+
// darker outline 25.19 took off the fields). It shows its state as the raised surface on the muted track, with
|
|
7498
|
+
// the default variant's shadow and its label's stronger colour
|
|
7499
|
+
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
6463
7500
|
variant === "default" && "shadow-[var(--ds-shadow-sm)]",
|
|
6464
7501
|
"transition-all motion-reduce:transition-none"
|
|
6465
7502
|
),
|
|
@@ -6533,12 +7570,13 @@ var ACCENT = {
|
|
|
6533
7570
|
var NEUTRAL = {
|
|
6534
7571
|
fill: "var(--ds-bg-muted)",
|
|
6535
7572
|
text: "var(--ds-text-primary)",
|
|
6536
|
-
edge: "var(--ds-
|
|
7573
|
+
edge: "var(--ds-control-edge-strong)"
|
|
6537
7574
|
};
|
|
6538
7575
|
function EventBar({ event, category, compact, onOpen, inert, showTime = true, continuesBefore, continuesAfter, className, style }) {
|
|
6539
7576
|
const ref = useRef(null);
|
|
6540
7577
|
const colours = eventColours(category);
|
|
6541
|
-
const
|
|
7578
|
+
const words = useDateWords();
|
|
7579
|
+
const name = eventName(event, category, words);
|
|
6542
7580
|
const look = cn(
|
|
6543
7581
|
"border-[length:var(--ds-border-width)] border-solid rounded-[var(--ds-radius-sm)]",
|
|
6544
7582
|
continuesBefore && "rounded-s-none border-s-0",
|
|
@@ -6591,17 +7629,18 @@ function EventBar({ event, category, compact, onOpen, inert, showTime = true, co
|
|
|
6591
7629
|
},
|
|
6592
7630
|
"aria-label": name,
|
|
6593
7631
|
children: [
|
|
6594
|
-
showTime && !event.allDay && /* @__PURE__ */ jsx("span", { className: "font-medium mr-ds-1", children: formatTime(event.start) }),
|
|
7632
|
+
showTime && !event.allDay && /* @__PURE__ */ jsx("span", { className: "font-medium mr-ds-1", children: words.formatTime(event.start) }),
|
|
6595
7633
|
event.title
|
|
6596
7634
|
]
|
|
6597
7635
|
}
|
|
6598
7636
|
);
|
|
6599
7637
|
}
|
|
6600
|
-
function eventName(event, category) {
|
|
6601
|
-
return [event.title, formatEventWhen(event, true), category?.label].filter(Boolean).join(", ");
|
|
7638
|
+
function eventName(event, category, words) {
|
|
7639
|
+
return [event.title, words.formatEventWhen(event, true), category?.label].filter(Boolean).join(", ");
|
|
6602
7640
|
}
|
|
6603
7641
|
var CALENDAR_LAYER = "data-calendar-layer";
|
|
6604
|
-
function EventCard({ event, category, anchor, actions, onClose, fallbackFocus }) {
|
|
7642
|
+
function EventCard({ event, category, anchor, actions, onClose, fallbackFocus, repeatSummary }) {
|
|
7643
|
+
const words = useDateWords();
|
|
6605
7644
|
const anchorRef = useMemo(() => ({ current: anchor }), [anchor]);
|
|
6606
7645
|
const panelRef = useRef(null);
|
|
6607
7646
|
const titleId = useId();
|
|
@@ -6645,14 +7684,14 @@ function EventCard({ event, category, anchor, actions, onClose, fallbackFocus })
|
|
|
6645
7684
|
};
|
|
6646
7685
|
}, [anchor, isTop, returnFocus, closeRef]);
|
|
6647
7686
|
const run = (action) => {
|
|
6648
|
-
const
|
|
7687
|
+
const list2 = anchor.closest(`[${CALENDAR_LAYER}]`);
|
|
6649
7688
|
returnFocus();
|
|
6650
7689
|
onClose();
|
|
6651
7690
|
action.onClick(event);
|
|
6652
7691
|
requestAnimationFrame(() => {
|
|
6653
7692
|
const now = document.activeElement;
|
|
6654
7693
|
if (now && now !== document.body && now.isConnected) return;
|
|
6655
|
-
if (
|
|
7694
|
+
if (list2?.isConnected && focusInitial(list2)) return;
|
|
6656
7695
|
fallbackFocus?.()?.focus();
|
|
6657
7696
|
});
|
|
6658
7697
|
};
|
|
@@ -6700,15 +7739,19 @@ function EventCard({ event, category, anchor, actions, onClose, fallbackFocus })
|
|
|
6700
7739
|
category.label
|
|
6701
7740
|
] }),
|
|
6702
7741
|
/* @__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) })
|
|
7742
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: words.formatEventWhen(event) }),
|
|
7743
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: words.formatEventWhen(event, true) })
|
|
7744
|
+
] }),
|
|
7745
|
+
repeatSummary && /* @__PURE__ */ jsxs("p", { "data-card-repeat": "", className: "text-xs text-[var(--ds-text-secondary)] flex items-start gap-ds-1", children: [
|
|
7746
|
+
/* @__PURE__ */ jsx(Icon, { name: "refresh", size: 14, className: "shrink-0 mt-px" }),
|
|
7747
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 break-words", children: repeatSummary })
|
|
6705
7748
|
] }),
|
|
6706
7749
|
event.location && /* @__PURE__ */ jsxs("p", { className: "text-xs text-[var(--ds-text-secondary)] flex items-start gap-ds-1", children: [
|
|
6707
7750
|
/* @__PURE__ */ jsx(Icon, { name: "map-pin", size: 14, className: "shrink-0 mt-px" }),
|
|
6708
7751
|
/* @__PURE__ */ jsx("span", { className: "min-w-0 break-words", children: event.location })
|
|
6709
7752
|
] }),
|
|
6710
7753
|
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: [
|
|
7754
|
+
event.attendees && event.attendees.length > 0 && /* @__PURE__ */ jsx("div", { ref: setAttendeeScroll, className: cn("max-h-32 overflow-y-auto -mx-[2px] p-[2px]", FOCUS_INSET), 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
7755
|
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "shrink-0", children: /* @__PURE__ */ jsx(Avatar, { size: "sm", initials: person.initials ?? person.name }) }),
|
|
6713
7756
|
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: person.name })
|
|
6714
7757
|
] }, `${person.name}-${i}`)) }) }),
|
|
@@ -6720,6 +7763,7 @@ function EventCard({ event, category, anchor, actions, onClose, fallbackFocus })
|
|
|
6720
7763
|
);
|
|
6721
7764
|
}
|
|
6722
7765
|
function DayList({ day, events, categories, anchor, onOpenEvent, onNewEvent, onClose }) {
|
|
7766
|
+
const { formatDayLong, formatDayShort } = useDateWords();
|
|
6723
7767
|
const anchorRef = useMemo(() => ({ current: anchor }), [anchor]);
|
|
6724
7768
|
const panelRef = useRef(null);
|
|
6725
7769
|
const pos = usePosition(anchorRef, panelRef, true, { side: "bottom", align: "start", offset: 4, flip: true });
|
|
@@ -6803,16 +7847,18 @@ var LANE_GAP = 4;
|
|
|
6803
7847
|
var NUMBER_ROW = 30;
|
|
6804
7848
|
var INSET = "var(--ds-space-1)";
|
|
6805
7849
|
function MonthView({ date, events, categories, selectedDate, onDayClick, canStartEvent, onOpenEvent, onNavigate, weekStartsOn }) {
|
|
7850
|
+
const { weekdayNames, formatDayLong, formatMonthYear } = useDateWords();
|
|
7851
|
+
const now = useToday();
|
|
6806
7852
|
const weeks = useMemo(() => getMonthGrid(date.getFullYear(), date.getMonth(), weekStartsOn), [date, weekStartsOn]);
|
|
6807
7853
|
const phone = useBreakpoint("sm");
|
|
6808
7854
|
const names = { short: weekdayNames(weekStartsOn, "short"), narrow: weekdayNames(weekStartsOn, "narrow"), long: weekdayNames(weekStartsOn, "long") };
|
|
6809
7855
|
const layouts = useMemo(() => weeks.map((week) => layoutWeek(events, week, LANES)), [weeks, events]);
|
|
6810
7856
|
const currentMonth = date.getMonth();
|
|
6811
7857
|
const gridRef = useRef(null);
|
|
6812
|
-
const [
|
|
7858
|
+
const [list2, setList] = useState(null);
|
|
6813
7859
|
const inMonth = (d) => !!d && d.getMonth() === currentMonth && d.getFullYear() === date.getFullYear();
|
|
6814
|
-
const fallback = inMonth(selectedDate) ? selectedDate : inMonth(
|
|
6815
|
-
const [activeDay, setActiveDay] = useState(
|
|
7860
|
+
const fallback = inMonth(selectedDate) ? selectedDate : inMonth(now) ? now : new Date(date.getFullYear(), currentMonth, 1);
|
|
7861
|
+
const [activeDay, setActiveDay] = useState(null);
|
|
6816
7862
|
const active = inMonth(activeDay) ? activeDay : fallback;
|
|
6817
7863
|
const openList = (day, anchor) => setList({ day, anchor });
|
|
6818
7864
|
const choose = (day, anchor) => phone ? openList(day, anchor) : onDayClick(day);
|
|
@@ -6836,7 +7882,7 @@ function MonthView({ date, events, categories, selectedDate, onDayClick, canStar
|
|
|
6836
7882
|
return /* @__PURE__ */ jsx("div", { role: "row", className: "relative grid grid-cols-7 flex-1", children: week.map((day, di) => {
|
|
6837
7883
|
const dayEvents = getEventsForDay(events, day);
|
|
6838
7884
|
const isCurrentMonth = day.getMonth() === currentMonth;
|
|
6839
|
-
const today =
|
|
7885
|
+
const today = now !== null && isSameDay(day, now);
|
|
6840
7886
|
const selected = !!selectedDate && isSameDay(day, selectedDate);
|
|
6841
7887
|
const weekend = isWeekend(day);
|
|
6842
7888
|
const more = layout.more[di];
|
|
@@ -6851,7 +7897,7 @@ function MonthView({ date, events, categories, selectedDate, onDayClick, canStar
|
|
|
6851
7897
|
"aria-selected": selected,
|
|
6852
7898
|
"aria-current": today ? "date" : void 0,
|
|
6853
7899
|
onFocus: () => {
|
|
6854
|
-
if (!isSameDay(day,
|
|
7900
|
+
if (!activeDay || !isSameDay(day, activeDay)) setActiveDay(day);
|
|
6855
7901
|
},
|
|
6856
7902
|
onClick: (e) => choose(day, e.currentTarget),
|
|
6857
7903
|
className: cn(
|
|
@@ -6900,7 +7946,7 @@ function MonthView({ date, events, categories, selectedDate, onDayClick, canStar
|
|
|
6900
7946
|
{
|
|
6901
7947
|
type: "button",
|
|
6902
7948
|
"aria-haspopup": "dialog",
|
|
6903
|
-
"aria-expanded": !!
|
|
7949
|
+
"aria-expanded": !!list2 && isSameDay(list2.day, day),
|
|
6904
7950
|
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
7951
|
style: { top: NUMBER_ROW + (LANES - 1) * (LANE_H + LANE_GAP), left: INSET, height: LANE_H },
|
|
6906
7952
|
onClick: (e) => {
|
|
@@ -6922,13 +7968,13 @@ function MonthView({ date, events, categories, selectedDate, onDayClick, canStar
|
|
|
6922
7968
|
}) }, dayKey(week[0]));
|
|
6923
7969
|
}) })
|
|
6924
7970
|
] }),
|
|
6925
|
-
|
|
7971
|
+
list2 && /* @__PURE__ */ jsx(
|
|
6926
7972
|
DayList,
|
|
6927
7973
|
{
|
|
6928
|
-
day:
|
|
6929
|
-
events: getEventsForDay(events,
|
|
7974
|
+
day: list2.day,
|
|
7975
|
+
events: getEventsForDay(events, list2.day),
|
|
6930
7976
|
categories,
|
|
6931
|
-
anchor:
|
|
7977
|
+
anchor: list2.anchor,
|
|
6932
7978
|
onOpenEvent,
|
|
6933
7979
|
onNewEvent: phone && canStartEvent ? onDayClick : void 0,
|
|
6934
7980
|
onClose: () => setList(null)
|
|
@@ -6964,6 +8010,7 @@ function NowLine() {
|
|
|
6964
8010
|
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
8011
|
}
|
|
6966
8012
|
function TimedEvent({ placed, category, onOpen, onFocusEvent }) {
|
|
8013
|
+
const words = useDateWords();
|
|
6967
8014
|
const { piece, column, columns } = placed;
|
|
6968
8015
|
const { event } = piece;
|
|
6969
8016
|
const top = timeToFraction(piece.start) * GRID_HEIGHT;
|
|
@@ -6979,7 +8026,7 @@ function TimedEvent({ placed, category, onOpen, onFocusEvent }) {
|
|
|
6979
8026
|
{
|
|
6980
8027
|
type: "button",
|
|
6981
8028
|
"data-calendar-event": event.id,
|
|
6982
|
-
"aria-label": eventName(event, category),
|
|
8029
|
+
"aria-label": eventName(event, category, words),
|
|
6983
8030
|
className: cn(
|
|
6984
8031
|
// a short event keeps its title whole: no padding above and below it
|
|
6985
8032
|
"absolute pointer-events-auto text-left px-ds-1.5 text-xs leading-tight",
|
|
@@ -7007,13 +8054,16 @@ function TimedEvent({ placed, category, onOpen, onFocusEvent }) {
|
|
|
7007
8054
|
onFocus: onFocusEvent,
|
|
7008
8055
|
children: [
|
|
7009
8056
|
/* @__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) })
|
|
8057
|
+
height > 30 && /* @__PURE__ */ jsx("span", { className: "text-2xs truncate w-full tabular-nums", children: words.formatTimeRange(event.start, end) })
|
|
7011
8058
|
]
|
|
7012
8059
|
}
|
|
7013
8060
|
);
|
|
7014
8061
|
}
|
|
7015
8062
|
function WeekView({ date, events, categories, selectedDate, onDayClick, onOpenEvent, onNavigate, weekStartsOn }) {
|
|
7016
8063
|
const days = useMemo(() => getWeekDays(date, weekStartsOn), [date, weekStartsOn]);
|
|
8064
|
+
const { weekdayNames, formatHourLabel, formatTime: formatTime2, formatDayLong, formatWeekRange } = useDateWords();
|
|
8065
|
+
const now = useToday();
|
|
8066
|
+
const isToday = (d) => now !== null && isSameDay(d, now);
|
|
7017
8067
|
const names = weekdayNames(weekStartsOn, "short");
|
|
7018
8068
|
const barEvents = useMemo(() => events.filter(isBarEvent), [events]);
|
|
7019
8069
|
const allDay = useMemo(() => layoutWeek(barEvents, days, ALL_DAY_LANES), [barEvents, days]);
|
|
@@ -7023,7 +8073,7 @@ function WeekView({ date, events, categories, selectedDate, onDayClick, onOpenEv
|
|
|
7023
8073
|
const scrollerRef = useRef(null);
|
|
7024
8074
|
const syncingScroll = useRef(false);
|
|
7025
8075
|
const { ref: edgesRef, measure: measureEdges, fadeProps: edgeFade } = useScrollEdges();
|
|
7026
|
-
const [
|
|
8076
|
+
const [list2, setList] = useState(null);
|
|
7027
8077
|
const handleScroll = useCallback((e) => {
|
|
7028
8078
|
if (syncingScroll.current) return;
|
|
7029
8079
|
syncingScroll.current = true;
|
|
@@ -7038,8 +8088,8 @@ function WeekView({ date, events, categories, selectedDate, onDayClick, onOpenEv
|
|
|
7038
8088
|
panels?.forEach((panel) => panel.addEventListener("scroll", handleScroll));
|
|
7039
8089
|
return () => panels?.forEach((panel) => panel.removeEventListener("scroll", handleScroll));
|
|
7040
8090
|
}, [handleScroll]);
|
|
7041
|
-
const
|
|
7042
|
-
const earliest = Math.floor(Math.min(WORKING_DAY, ...
|
|
8091
|
+
const starts2 = pieces.flat().filter((p) => p.piece.start.getTime() === p.piece.event.start.getTime()).map((p) => p.piece.start.getHours() + p.piece.start.getMinutes() / 60);
|
|
8092
|
+
const earliest = Math.floor(Math.min(WORKING_DAY, ...starts2));
|
|
7043
8093
|
const topOf = (hour) => Math.max(0, hour * HOUR_HEIGHT - HOUR_LABEL_ROOM);
|
|
7044
8094
|
const openingHourRef = useLatest(earliest);
|
|
7045
8095
|
const opened = useRef(null);
|
|
@@ -7079,8 +8129,8 @@ function WeekView({ date, events, categories, selectedDate, onDayClick, onOpenEv
|
|
|
7079
8129
|
}, [earliest, week]);
|
|
7080
8130
|
const inWeek = (d) => days.some((day) => isSameDay(day, d));
|
|
7081
8131
|
const anchorDay = selectedDate && inWeek(selectedDate) ? selectedDate : days.find(isToday) ?? days[0];
|
|
7082
|
-
const [activeKey, setActiveKey] = useState(
|
|
7083
|
-
const active = inWeek(parseKey(activeKey).day) ? activeKey : cellKey(anchorDay, parseKey(activeKey).hour);
|
|
8132
|
+
const [activeKey, setActiveKey] = useState(null);
|
|
8133
|
+
const active = activeKey !== null && inWeek(parseKey(activeKey).day) ? activeKey : cellKey(anchorDay, activeKey !== null ? parseKey(activeKey).hour : openingHour);
|
|
7084
8134
|
const firstVisibleHour = () => Math.min(23, Math.ceil((scrollerRef.current?.scrollTop ?? 0) / HOUR_HEIGHT));
|
|
7085
8135
|
const placeInView = (_key, el) => {
|
|
7086
8136
|
const scroller = scrollerRef.current;
|
|
@@ -7165,7 +8215,7 @@ function WeekView({ date, events, categories, selectedDate, onDayClick, onOpenEv
|
|
|
7165
8215
|
tabIndex: grid.tabIndexOf(key),
|
|
7166
8216
|
"aria-label": `${formatDayLong(day)}, all day`,
|
|
7167
8217
|
onFocus: () => {
|
|
7168
|
-
if (
|
|
8218
|
+
if (activeKey !== key) setActiveKey(key);
|
|
7169
8219
|
},
|
|
7170
8220
|
onClick: () => onDayClick(day),
|
|
7171
8221
|
className: cn("relative cursor-pointer", FOCUS_INSET, i > 0 && "border-l-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]"),
|
|
@@ -7193,7 +8243,7 @@ function WeekView({ date, events, categories, selectedDate, onDayClick, onOpenEv
|
|
|
7193
8243
|
{
|
|
7194
8244
|
type: "button",
|
|
7195
8245
|
"aria-haspopup": "dialog",
|
|
7196
|
-
"aria-expanded": !!
|
|
8246
|
+
"aria-expanded": !!list2 && isSameDay(list2.day, day),
|
|
7197
8247
|
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
8248
|
style: { top: 2 + (ALL_DAY_LANES - 1) * (LANE_H2 + LANE_GAP2), left: 2, height: LANE_H2 },
|
|
7199
8249
|
onClick: (e) => {
|
|
@@ -7224,9 +8274,9 @@ function WeekView({ date, events, categories, selectedDate, onDayClick, onOpenEv
|
|
|
7224
8274
|
role: "gridcell",
|
|
7225
8275
|
"data-grid-key": key,
|
|
7226
8276
|
tabIndex: grid.tabIndexOf(key),
|
|
7227
|
-
"aria-label": `${formatDayLong(day)}, ${
|
|
8277
|
+
"aria-label": `${formatDayLong(day)}, ${formatTime2(new Date(day.getFullYear(), day.getMonth(), day.getDate(), hour))}`,
|
|
7228
8278
|
onFocus: () => {
|
|
7229
|
-
if (
|
|
8279
|
+
if (activeKey !== key) setActiveKey(key);
|
|
7230
8280
|
},
|
|
7231
8281
|
onClick: chooseHour(day, hour),
|
|
7232
8282
|
className: cn(
|
|
@@ -7253,18 +8303,21 @@ function WeekView({ date, events, categories, selectedDate, onDayClick, onOpenEv
|
|
|
7253
8303
|
] }, i)) })
|
|
7254
8304
|
] }) })
|
|
7255
8305
|
] }),
|
|
7256
|
-
|
|
8306
|
+
list2 && /* @__PURE__ */ jsx(DayList, { day: list2.day, events: getEventsForDay(barEvents, list2.day), categories, anchor: list2.anchor, onOpenEvent, onClose: () => setList(null) })
|
|
7257
8307
|
] });
|
|
7258
8308
|
}
|
|
7259
8309
|
var WEEKS_SHOWN = 6;
|
|
7260
8310
|
var COLS = WEEKS_SHOWN * 7;
|
|
8311
|
+
var NONE = [];
|
|
7261
8312
|
function DayCellWithPopover({
|
|
7262
8313
|
day,
|
|
7263
8314
|
month,
|
|
7264
8315
|
events,
|
|
7265
8316
|
categories,
|
|
7266
8317
|
selectedDate,
|
|
7267
|
-
isEvenRow
|
|
8318
|
+
isEvenRow,
|
|
8319
|
+
today: now,
|
|
8320
|
+
words
|
|
7268
8321
|
}) {
|
|
7269
8322
|
const [open, setOpen] = useState(false);
|
|
7270
8323
|
const cellRef = useRef(null);
|
|
@@ -7277,8 +8330,8 @@ function DayCellWithPopover({
|
|
|
7277
8330
|
});
|
|
7278
8331
|
const hoverTimeout = useRef(void 0);
|
|
7279
8332
|
const inMonth = day.getMonth() === month;
|
|
7280
|
-
const dayEvents = inMonth ?
|
|
7281
|
-
const today = inMonth &&
|
|
8333
|
+
const dayEvents = inMonth ? events : NONE;
|
|
8334
|
+
const today = inMonth && now !== null && isSameDay(day, now);
|
|
7282
8335
|
const selected = inMonth && selectedDate && isSameDay(day, selectedDate);
|
|
7283
8336
|
const hasEvents = dayEvents.length > 0;
|
|
7284
8337
|
const handleMouseEnter = () => {
|
|
@@ -7334,7 +8387,7 @@ function DayCellWithPopover({
|
|
|
7334
8387
|
style: { top: pos.top, left: pos.left },
|
|
7335
8388
|
role: "tooltip",
|
|
7336
8389
|
children: [
|
|
7337
|
-
/* @__PURE__ */ jsx("p", { className: "text-2xs font-medium text-[var(--ds-text-muted)] px-ds-1 mb-ds-0.5", children: formatDayShort(day) }),
|
|
8390
|
+
/* @__PURE__ */ jsx("p", { className: "text-2xs font-medium text-[var(--ds-text-muted)] px-ds-1 mb-ds-0.5", children: words.formatDayShort(day) }),
|
|
7338
8391
|
dayEvents.map((event) => /* @__PURE__ */ jsx(EventBar, { event, category: categories[event.category ?? ""], inert: true }, event.id))
|
|
7339
8392
|
]
|
|
7340
8393
|
}
|
|
@@ -7348,11 +8401,13 @@ function DayCellWithPopover({
|
|
|
7348
8401
|
function MonthRow({
|
|
7349
8402
|
year,
|
|
7350
8403
|
month,
|
|
7351
|
-
|
|
8404
|
+
byDay,
|
|
7352
8405
|
categories,
|
|
7353
8406
|
selectedDate,
|
|
7354
8407
|
onClick,
|
|
7355
|
-
weekStartsOn
|
|
8408
|
+
weekStartsOn,
|
|
8409
|
+
today,
|
|
8410
|
+
words
|
|
7356
8411
|
}) {
|
|
7357
8412
|
const grid = useMemo(
|
|
7358
8413
|
() => getMonthGrid(year, month, weekStartsOn),
|
|
@@ -7361,15 +8416,18 @@ function MonthRow({
|
|
|
7361
8416
|
const flat = grid.flat();
|
|
7362
8417
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7363
8418
|
/* @__PURE__ */ jsx(
|
|
7364
|
-
"
|
|
8419
|
+
"button",
|
|
7365
8420
|
{
|
|
8421
|
+
type: "button",
|
|
8422
|
+
"aria-label": `${words.monthName(month, "short")} ${year}`,
|
|
7366
8423
|
className: cn(
|
|
7367
8424
|
"sticky left-0 z-10 flex items-center justify-center px-ds-2 text-xs font-semibold text-[var(--ds-text-primary)]",
|
|
7368
8425
|
"bg-[var(--ds-bg-muted)] cursor-pointer hover:text-[var(--ds-accent-primary)] transition-colors",
|
|
7369
|
-
"border-r-[length:var(--ds-divider-width)] border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]"
|
|
8426
|
+
"border-r-[length:var(--ds-divider-width)] border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]",
|
|
8427
|
+
FOCUS_INSET
|
|
7370
8428
|
),
|
|
7371
8429
|
onClick,
|
|
7372
|
-
children: monthName(month, "short")
|
|
8430
|
+
children: words.monthName(month, "short")
|
|
7373
8431
|
}
|
|
7374
8432
|
),
|
|
7375
8433
|
flat.map((day, i) => /* @__PURE__ */ jsx(
|
|
@@ -7377,10 +8435,12 @@ function MonthRow({
|
|
|
7377
8435
|
{
|
|
7378
8436
|
day,
|
|
7379
8437
|
month,
|
|
7380
|
-
events,
|
|
8438
|
+
events: byDay.get(dayKey(day)) ?? NONE,
|
|
7381
8439
|
categories,
|
|
7382
8440
|
selectedDate,
|
|
7383
|
-
isEvenRow: month % 2 === 0
|
|
8441
|
+
isEvenRow: month % 2 === 0,
|
|
8442
|
+
today,
|
|
8443
|
+
words
|
|
7384
8444
|
},
|
|
7385
8445
|
i
|
|
7386
8446
|
))
|
|
@@ -7395,7 +8455,10 @@ function YearView({
|
|
|
7395
8455
|
weekStartsOn
|
|
7396
8456
|
}) {
|
|
7397
8457
|
const year = date.getFullYear();
|
|
7398
|
-
const
|
|
8458
|
+
const words = useDateWords();
|
|
8459
|
+
const today = useToday();
|
|
8460
|
+
const dayNames = words.weekdayNames(weekStartsOn, "narrow");
|
|
8461
|
+
const byDay = useMemo(() => groupEventsByDay(events, new Date(year, 0, 1), new Date(year + 1, 0, 1)), [events, year]);
|
|
7399
8462
|
const repeatedHeaders = useMemo(() => {
|
|
7400
8463
|
const headers = [];
|
|
7401
8464
|
for (let w = 0; w < WEEKS_SHOWN; w++) {
|
|
@@ -7432,11 +8495,13 @@ function YearView({
|
|
|
7432
8495
|
{
|
|
7433
8496
|
year,
|
|
7434
8497
|
month,
|
|
7435
|
-
|
|
8498
|
+
byDay,
|
|
7436
8499
|
categories,
|
|
7437
8500
|
selectedDate,
|
|
7438
8501
|
onClick: () => onMonthClick(month),
|
|
7439
|
-
weekStartsOn
|
|
8502
|
+
weekStartsOn,
|
|
8503
|
+
today,
|
|
8504
|
+
words
|
|
7440
8505
|
},
|
|
7441
8506
|
month
|
|
7442
8507
|
))
|
|
@@ -7445,14 +8510,16 @@ function YearView({
|
|
|
7445
8510
|
) });
|
|
7446
8511
|
}
|
|
7447
8512
|
function CompactMonthView({ date, events, categories, selectedDate, onDayClick, onOpenEvent, onNavigate, weekStartsOn }) {
|
|
8513
|
+
const { weekdayNames, formatDayLong, formatMonthYear } = useDateWords();
|
|
8514
|
+
const now = useToday();
|
|
7448
8515
|
const weeks = useMemo(() => getMonthGrid(date.getFullYear(), date.getMonth(), weekStartsOn), [date, weekStartsOn]);
|
|
7449
8516
|
const names = { narrow: weekdayNames(weekStartsOn, "narrow"), long: weekdayNames(weekStartsOn, "long") };
|
|
7450
8517
|
const currentMonth = date.getMonth();
|
|
7451
8518
|
const gridRef = useRef(null);
|
|
7452
|
-
const [
|
|
8519
|
+
const [list2, setList] = useState(null);
|
|
7453
8520
|
const inMonth = (d) => !!d && d.getMonth() === currentMonth && d.getFullYear() === date.getFullYear();
|
|
7454
|
-
const fallback = inMonth(selectedDate) ? selectedDate : inMonth(
|
|
7455
|
-
const [activeDay, setActiveDay] = useState(
|
|
8521
|
+
const fallback = inMonth(selectedDate) ? selectedDate : inMonth(now) ? now : new Date(date.getFullYear(), currentMonth, 1);
|
|
8522
|
+
const [activeDay, setActiveDay] = useState(null);
|
|
7456
8523
|
const active = inMonth(activeDay) ? activeDay : fallback;
|
|
7457
8524
|
const grid = useGridKeyboard({
|
|
7458
8525
|
container: gridRef,
|
|
@@ -7470,7 +8537,7 @@ function CompactMonthView({ date, events, categories, selectedDate, onDayClick,
|
|
|
7470
8537
|
weeks.map((week) => /* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7", children: week.map((day) => {
|
|
7471
8538
|
const isCurrentMonth = day.getMonth() === currentMonth;
|
|
7472
8539
|
const dayEvents = isCurrentMonth ? getEventsForDay(events, day) : [];
|
|
7473
|
-
const today = isCurrentMonth &&
|
|
8540
|
+
const today = isCurrentMonth && now !== null && isSameDay(day, now);
|
|
7474
8541
|
const selected = isCurrentMonth && !!selectedDate && isSameDay(day, selectedDate);
|
|
7475
8542
|
return /* @__PURE__ */ jsxs(
|
|
7476
8543
|
"button",
|
|
@@ -7483,7 +8550,7 @@ function CompactMonthView({ date, events, categories, selectedDate, onDayClick,
|
|
|
7483
8550
|
"aria-selected": selected,
|
|
7484
8551
|
"aria-current": today ? "date" : void 0,
|
|
7485
8552
|
onFocus: () => {
|
|
7486
|
-
if (!isSameDay(day,
|
|
8553
|
+
if (!activeDay || !isSameDay(day, activeDay)) setActiveDay(day);
|
|
7487
8554
|
},
|
|
7488
8555
|
onClick: (e) => {
|
|
7489
8556
|
onDayClick(day);
|
|
@@ -7506,7 +8573,7 @@ function CompactMonthView({ date, events, categories, selectedDate, onDayClick,
|
|
|
7506
8573
|
);
|
|
7507
8574
|
}) }, dayKey(week[0])))
|
|
7508
8575
|
] }),
|
|
7509
|
-
|
|
8576
|
+
list2 && /* @__PURE__ */ jsx(DayList, { day: list2.day, events: getEventsForDay(events, list2.day), categories, anchor: list2.anchor, onOpenEvent, onClose: () => setList(null) })
|
|
7510
8577
|
] });
|
|
7511
8578
|
}
|
|
7512
8579
|
|
|
@@ -7539,10 +8606,19 @@ var viewLabels = {
|
|
|
7539
8606
|
year: "Year"
|
|
7540
8607
|
};
|
|
7541
8608
|
var VIEWS = ["week", "month", "year"];
|
|
8609
|
+
var PENDING_HEAD = { default: "h-[97px] @min-[500px]:h-[49px]", compact: "h-[41px]" };
|
|
8610
|
+
var PENDING_BODY = {
|
|
8611
|
+
month: "h-[513px] sm:h-[633px]",
|
|
8612
|
+
week: "h-[1056px]",
|
|
8613
|
+
year: "h-[455px]",
|
|
8614
|
+
compact: "h-[332px]"
|
|
8615
|
+
};
|
|
8616
|
+
var NO_EVENTS = [];
|
|
7542
8617
|
function MonthDropdown({
|
|
7543
8618
|
currentDate,
|
|
7544
8619
|
onSelect
|
|
7545
8620
|
}) {
|
|
8621
|
+
const { formatMonthYear, monthName: monthName2 } = useDateWords();
|
|
7546
8622
|
const [open, setOpen] = useState(false);
|
|
7547
8623
|
const [browseYear, setBrowseYear] = useState(currentDate.getFullYear());
|
|
7548
8624
|
const triggerRef = useRef(null);
|
|
@@ -7642,7 +8718,7 @@ function MonthDropdown({
|
|
|
7642
8718
|
}
|
|
7643
8719
|
)
|
|
7644
8720
|
] }),
|
|
7645
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-ds-1", children: Array.from({ length: 12 }, (_, i) =>
|
|
8721
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-ds-1", children: Array.from({ length: 12 }, (_, i) => monthName2(i, "short")).map((name, i) => {
|
|
7646
8722
|
const isActive2 = i === currentMonth && browseYear === currentYear;
|
|
7647
8723
|
return /* @__PURE__ */ jsx(
|
|
7648
8724
|
"button",
|
|
@@ -7815,10 +8891,14 @@ function Calendar({
|
|
|
7815
8891
|
onDayClick,
|
|
7816
8892
|
eventActions,
|
|
7817
8893
|
categories = DEFAULT_CATEGORIES,
|
|
7818
|
-
weekStartsOn
|
|
8894
|
+
weekStartsOn: weekStartsOnProp,
|
|
7819
8895
|
size = "default",
|
|
7820
8896
|
className
|
|
7821
8897
|
}) {
|
|
8898
|
+
const weekStartsOn = useWeekStart(weekStartsOnProp);
|
|
8899
|
+
const { formatWeekRange, formatMonthYear } = useDateWords();
|
|
8900
|
+
const locale = useFormatLocale();
|
|
8901
|
+
const hydrated = useHydrated();
|
|
7822
8902
|
const [currentView, setCurrentView] = useControllableState(
|
|
7823
8903
|
controlledView,
|
|
7824
8904
|
defaultView,
|
|
@@ -7885,6 +8965,32 @@ function Calendar({
|
|
|
7885
8965
|
useEffect(() => {
|
|
7886
8966
|
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
8967
|
}, [unreadable]);
|
|
8968
|
+
const drawnFrom = useMemo(() => {
|
|
8969
|
+
if (currentView === "week") return startOfWeek(currentDate, weekStartsOn);
|
|
8970
|
+
if (currentView === "year") return new Date(currentDate.getFullYear(), 0, 1);
|
|
8971
|
+
return getMonthGrid(currentDate.getFullYear(), currentDate.getMonth(), weekStartsOn)[0][0];
|
|
8972
|
+
}, [currentView, currentDate, weekStartsOn]);
|
|
8973
|
+
const drawnTo = useMemo(() => {
|
|
8974
|
+
if (currentView === "week") return addDays2(drawnFrom, 7);
|
|
8975
|
+
if (currentView === "year") return new Date(drawnFrom.getFullYear() + 1, 0, 1);
|
|
8976
|
+
return addDays2(drawnFrom, 42);
|
|
8977
|
+
}, [currentView, drawnFrom]);
|
|
8978
|
+
const { drawnEvents, unreadableRepeats } = useMemo(() => {
|
|
8979
|
+
const out = [];
|
|
8980
|
+
const odd = [];
|
|
8981
|
+
for (const e of stableEvents) {
|
|
8982
|
+
if (!e.repeat) {
|
|
8983
|
+
out.push(e);
|
|
8984
|
+
continue;
|
|
8985
|
+
}
|
|
8986
|
+
if (!readRecurrence(e.repeat)) odd.push(String(e.id));
|
|
8987
|
+
out.push(...occurrences(e, drawnFrom, drawnTo));
|
|
8988
|
+
}
|
|
8989
|
+
return { drawnEvents: out, unreadableRepeats: odd.join(", ") };
|
|
8990
|
+
}, [stableEvents, drawnFrom, drawnTo]);
|
|
8991
|
+
useEffect(() => {
|
|
8992
|
+
if (unreadableRepeats) warnOnce("Calendar", `events whose repeat it can't read are drawn once (${unreadableRepeats}): pass RecurrencePicker's rule, or an RRULE in the subset parseRRule reads.`);
|
|
8993
|
+
}, [unreadableRepeats]);
|
|
7888
8994
|
useEffect(() => {
|
|
7889
8995
|
if (!onDateRangeChange) return;
|
|
7890
8996
|
let start, end;
|
|
@@ -7924,35 +9030,133 @@ function Calendar({
|
|
|
7924
9030
|
},
|
|
7925
9031
|
[onDayClick]
|
|
7926
9032
|
);
|
|
9033
|
+
const viewRef = useRef(null);
|
|
9034
|
+
const focusGridNext = useRef(null);
|
|
7927
9035
|
const handleMonthClick = useCallback(
|
|
7928
9036
|
(month) => {
|
|
9037
|
+
focusGridNext.current = { year: currentDate.getFullYear(), month, until: Date.now() + 2e3 };
|
|
7929
9038
|
setCurrentDate(new Date(currentDate.getFullYear(), month, 1));
|
|
7930
9039
|
setCurrentView("month");
|
|
7931
9040
|
},
|
|
7932
9041
|
[currentDate, setCurrentDate, setCurrentView]
|
|
7933
9042
|
);
|
|
9043
|
+
useEffect(() => {
|
|
9044
|
+
const wish = focusGridNext.current;
|
|
9045
|
+
if (!wish) return;
|
|
9046
|
+
if (Date.now() > wish.until || currentView !== "month" && currentView !== "year") {
|
|
9047
|
+
focusGridNext.current = null;
|
|
9048
|
+
return;
|
|
9049
|
+
}
|
|
9050
|
+
if (currentView !== "month" || currentDate.getFullYear() !== wish.year || currentDate.getMonth() !== wish.month) return;
|
|
9051
|
+
focusGridNext.current = null;
|
|
9052
|
+
viewRef.current?.querySelector('[role="grid"] [role="gridcell"][tabindex="0"]')?.focus();
|
|
9053
|
+
}, [currentView, currentDate]);
|
|
7934
9054
|
const headerLabel = useMemo(() => {
|
|
7935
9055
|
if (currentView === "week") return formatWeekRange(currentDate, weekStartsOn);
|
|
7936
9056
|
return void 0;
|
|
7937
|
-
}, [currentView, currentDate, weekStartsOn]);
|
|
7938
|
-
const
|
|
9057
|
+
}, [currentView, currentDate, weekStartsOn, formatWeekRange]);
|
|
9058
|
+
const lastEvent = useRef(null);
|
|
9059
|
+
const drawnRef = useLatest(drawnEvents);
|
|
9060
|
+
const rememberEvent = useCallback((e) => {
|
|
9061
|
+
const id = e.target.closest?.("[data-calendar-event]")?.getAttribute("data-calendar-event");
|
|
9062
|
+
const event = id ? drawnRef.current.find((x) => x.id === id) : void 0;
|
|
9063
|
+
if (event) lastEvent.current = event;
|
|
9064
|
+
}, [drawnRef]);
|
|
9065
|
+
const forgetEvent = useCallback((e) => {
|
|
9066
|
+
const to = e.relatedTarget;
|
|
9067
|
+
if (to && (rootRef.current?.contains(to) || to.closest('[role="dialog"], [role="alertdialog"]'))) return;
|
|
9068
|
+
lastEvent.current = null;
|
|
9069
|
+
}, []);
|
|
9070
|
+
useEffect(() => {
|
|
9071
|
+
const gone = lastEvent.current;
|
|
9072
|
+
if (!gone || drawnEvents.some((e) => e.id === gone.id)) return;
|
|
9073
|
+
const key = currentView === "week" && !gone.allDay ? `${dayKey(gone.start)}T${String(gone.start.getHours()).padStart(2, "0")}` : dayKey(gone.start);
|
|
9074
|
+
const fallen = () => {
|
|
9075
|
+
const active = document.activeElement;
|
|
9076
|
+
return !active || active === document.body || !active.isConnected;
|
|
9077
|
+
};
|
|
9078
|
+
const inOverlay = () => !!document.activeElement?.closest?.('[role="dialog"], [role="alertdialog"]');
|
|
9079
|
+
const SETTLE_MS = 120;
|
|
9080
|
+
let check;
|
|
9081
|
+
const settle = () => {
|
|
9082
|
+
if (fallen()) {
|
|
9083
|
+
rootRef.current?.querySelector(`[role="gridcell"][data-grid-key="${key}"]`)?.focus();
|
|
9084
|
+
stop();
|
|
9085
|
+
return;
|
|
9086
|
+
}
|
|
9087
|
+
if (!inOverlay()) {
|
|
9088
|
+
stop();
|
|
9089
|
+
return;
|
|
9090
|
+
}
|
|
9091
|
+
check = setTimeout(settle, SETTLE_MS);
|
|
9092
|
+
};
|
|
9093
|
+
const onOut = () => {
|
|
9094
|
+
clearTimeout(check);
|
|
9095
|
+
check = setTimeout(settle, SETTLE_MS);
|
|
9096
|
+
};
|
|
9097
|
+
check = setTimeout(settle, SETTLE_MS);
|
|
9098
|
+
const timer = setTimeout(() => stop(), 1e4);
|
|
9099
|
+
function stop() {
|
|
9100
|
+
document.removeEventListener("focusout", onOut, true);
|
|
9101
|
+
clearTimeout(timer);
|
|
9102
|
+
clearTimeout(check);
|
|
9103
|
+
lastEvent.current = null;
|
|
9104
|
+
}
|
|
9105
|
+
document.addEventListener("focusout", onOut, true);
|
|
9106
|
+
return () => {
|
|
9107
|
+
document.removeEventListener("focusout", onOut, true);
|
|
9108
|
+
clearTimeout(timer);
|
|
9109
|
+
clearTimeout(check);
|
|
9110
|
+
};
|
|
9111
|
+
}, [drawnEvents, currentView]);
|
|
9112
|
+
const live = openEvent && drawnEvents.find((e) => e.id === openEvent.event.id);
|
|
9113
|
+
const series = live?.series ? stableEvents.find((e) => e.id === live.series.id) : live?.repeat ? live : void 0;
|
|
9114
|
+
const seriesRule = series ? readRecurrence(series.repeat) : null;
|
|
9115
|
+
const repeatSummary = series?.repeat ? seriesRule ? describeRecurrence(seriesRule, series.start, locale) : "Repeats" : void 0;
|
|
7939
9116
|
const card = openEvent && live ? /* @__PURE__ */ jsx(
|
|
7940
9117
|
EventCard,
|
|
7941
9118
|
{
|
|
7942
9119
|
event: live,
|
|
7943
9120
|
category: categories[live.category ?? ""],
|
|
7944
9121
|
anchor: openEvent.anchor,
|
|
9122
|
+
repeatSummary,
|
|
7945
9123
|
actions: typeof eventActions === "function" ? eventActions(live) : eventActions ?? [],
|
|
7946
9124
|
onClose: () => setOpenEvent(null),
|
|
7947
9125
|
fallbackFocus: () => rootRef.current?.querySelector('[role="gridcell"][tabindex="0"]')
|
|
7948
9126
|
},
|
|
7949
9127
|
openEvent.event.id
|
|
7950
9128
|
) : null;
|
|
9129
|
+
const shownEvents = hydrated ? drawnEvents : NO_EVENTS;
|
|
9130
|
+
if (!hydrated) {
|
|
9131
|
+
return /* @__PURE__ */ jsxs(
|
|
9132
|
+
"div",
|
|
9133
|
+
{
|
|
9134
|
+
ref: containerRef,
|
|
9135
|
+
"aria-busy": "true",
|
|
9136
|
+
"data-calendar-pending": "",
|
|
9137
|
+
className: cn(
|
|
9138
|
+
"flex flex-col @container",
|
|
9139
|
+
"bg-[var(--ds-bg-surface)]",
|
|
9140
|
+
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
9141
|
+
size === "compact" ? "rounded-[var(--ds-radius-md)]" : "rounded-[var(--ds-radius-lg)]",
|
|
9142
|
+
"shadow-[var(--ds-shadow-sm)]",
|
|
9143
|
+
"overflow-hidden",
|
|
9144
|
+
className
|
|
9145
|
+
),
|
|
9146
|
+
children: [
|
|
9147
|
+
/* @__PURE__ */ jsx("div", { className: cn("bg-[var(--ds-bg-muted)] border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]", size === "compact" ? PENDING_HEAD.compact : PENDING_HEAD.default) }),
|
|
9148
|
+
/* @__PURE__ */ jsx("div", { className: size === "compact" ? PENDING_BODY.compact : PENDING_BODY[currentView] })
|
|
9149
|
+
]
|
|
9150
|
+
}
|
|
9151
|
+
);
|
|
9152
|
+
}
|
|
7951
9153
|
if (size === "compact") {
|
|
7952
9154
|
return /* @__PURE__ */ jsxs(
|
|
7953
9155
|
"div",
|
|
7954
9156
|
{
|
|
7955
9157
|
ref: containerRef,
|
|
9158
|
+
onFocus: rememberEvent,
|
|
9159
|
+
onBlur: forgetEvent,
|
|
7956
9160
|
className: cn(
|
|
7957
9161
|
"flex flex-col",
|
|
7958
9162
|
"bg-[var(--ds-bg-surface)]",
|
|
@@ -8006,7 +9210,7 @@ function Calendar({
|
|
|
8006
9210
|
CompactMonthView,
|
|
8007
9211
|
{
|
|
8008
9212
|
date: currentDate,
|
|
8009
|
-
events:
|
|
9213
|
+
events: shownEvents,
|
|
8010
9214
|
categories,
|
|
8011
9215
|
selectedDate,
|
|
8012
9216
|
onDayClick: handleDayClick,
|
|
@@ -8024,6 +9228,8 @@ function Calendar({
|
|
|
8024
9228
|
"div",
|
|
8025
9229
|
{
|
|
8026
9230
|
ref: containerRef,
|
|
9231
|
+
onFocus: rememberEvent,
|
|
9232
|
+
onBlur: forgetEvent,
|
|
8027
9233
|
"data-fill": fill2 != null ? "" : void 0,
|
|
8028
9234
|
className: cn(
|
|
8029
9235
|
"flex flex-col",
|
|
@@ -8094,12 +9300,12 @@ function Calendar({
|
|
|
8094
9300
|
]
|
|
8095
9301
|
}
|
|
8096
9302
|
),
|
|
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: [
|
|
9303
|
+
/* @__PURE__ */ jsxs("div", { ref: viewRef, className: "flex-1 min-h-0", style: { minHeight: currentView === "week" ? fill2 != null || inPane ? void 0 : 420 : currentView === "month" ? isNarrow ? 360 : 500 : void 0 }, children: [
|
|
8098
9304
|
currentView === "month" && /* @__PURE__ */ jsx(
|
|
8099
9305
|
MonthView,
|
|
8100
9306
|
{
|
|
8101
9307
|
date: currentDate,
|
|
8102
|
-
events:
|
|
9308
|
+
events: shownEvents,
|
|
8103
9309
|
categories,
|
|
8104
9310
|
selectedDate,
|
|
8105
9311
|
onDayClick: handleDayClick,
|
|
@@ -8113,7 +9319,7 @@ function Calendar({
|
|
|
8113
9319
|
WeekView,
|
|
8114
9320
|
{
|
|
8115
9321
|
date: currentDate,
|
|
8116
|
-
events:
|
|
9322
|
+
events: shownEvents,
|
|
8117
9323
|
categories,
|
|
8118
9324
|
selectedDate,
|
|
8119
9325
|
onDayClick: handleDayClick,
|
|
@@ -8126,7 +9332,7 @@ function Calendar({
|
|
|
8126
9332
|
YearView,
|
|
8127
9333
|
{
|
|
8128
9334
|
date: currentDate,
|
|
8129
|
-
events:
|
|
9335
|
+
events: shownEvents,
|
|
8130
9336
|
categories,
|
|
8131
9337
|
selectedDate,
|
|
8132
9338
|
onMonthClick: handleMonthClick,
|
|
@@ -8201,7 +9407,7 @@ var defaultIcons = {
|
|
|
8201
9407
|
var FRAME_ICON_SIZE = 28;
|
|
8202
9408
|
function renderIcon(icon) {
|
|
8203
9409
|
if (typeof icon === "string") return /* @__PURE__ */ jsx(Icon, { name: icon, size: FRAME_ICON_SIZE, className: "text-[var(--ds-text-muted)]", from: "EmptyState's icon" });
|
|
8204
|
-
if (isValidElement(icon) && icon.type === Icon) return cloneElement(icon, { size: FRAME_ICON_SIZE });
|
|
9410
|
+
if (isValidElement(icon) && elementType(icon.type) === Icon) return cloneElement(icon, { size: FRAME_ICON_SIZE });
|
|
8205
9411
|
return icon;
|
|
8206
9412
|
}
|
|
8207
9413
|
function EmptyState({ icon, iconFrame = "circle", title, description, action, variant = "empty", bordered = false, style: styleProp, className }) {
|
|
@@ -8459,30 +9665,32 @@ function HorizontalLayout({ items, minItemWidth, className }) {
|
|
|
8459
9665
|
] }, i);
|
|
8460
9666
|
}) });
|
|
8461
9667
|
}
|
|
8462
|
-
var
|
|
8463
|
-
var
|
|
9668
|
+
var exactFormat = (locale, d) => new Intl.DateTimeFormat(locale, { dateStyle: "medium", timeStyle: "short" }).format(d);
|
|
9669
|
+
var exactDayFormat = (locale, d) => new Intl.DateTimeFormat(locale, { dateStyle: "medium" }).format(d);
|
|
8464
9670
|
var DATE_ONLY = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
8465
|
-
function exactTime(value) {
|
|
9671
|
+
function exactTime(value, locale) {
|
|
8466
9672
|
if (typeof value === "string") {
|
|
8467
9673
|
const day = DATE_ONLY.exec(value.trim());
|
|
8468
9674
|
if (day) {
|
|
8469
9675
|
const [y, m, d] = [Number(day[1]), Number(day[2]) - 1, Number(day[3])];
|
|
8470
9676
|
const date2 = new Date(y, m, d);
|
|
8471
|
-
return date2.getFullYear() === y && date2.getMonth() === m && date2.getDate() === d ? { iso: value.trim(), text:
|
|
9677
|
+
return date2.getFullYear() === y && date2.getMonth() === m && date2.getDate() === d ? { iso: value.trim(), text: exactDayFormat(locale, date2) } : null;
|
|
8472
9678
|
}
|
|
8473
9679
|
}
|
|
8474
9680
|
const date = value instanceof Date ? value : new Date(value);
|
|
8475
|
-
return Number.isNaN(date.getTime()) ? null : { iso: date.toISOString(), text:
|
|
9681
|
+
return Number.isNaN(date.getTime()) ? null : { iso: date.toISOString(), text: exactFormat(locale, date) };
|
|
8476
9682
|
}
|
|
8477
9683
|
function ItemTime({ item }) {
|
|
9684
|
+
const locale = useFormatLocale();
|
|
9685
|
+
const hydrated = useHydrated();
|
|
8478
9686
|
if (item.time !== void 0) {
|
|
8479
9687
|
return /* @__PURE__ */ jsx("p", { className: "text-2xs text-[var(--ds-text-muted)] mt-ds-0.5 tabular-nums", children: /* @__PURE__ */ jsx(RelativeTime, { time: item.time }) });
|
|
8480
9688
|
}
|
|
8481
|
-
const exact = item.dateTime ? exactTime(item.dateTime) : null;
|
|
9689
|
+
const exact = item.dateTime ? exactTime(item.dateTime, locale) : null;
|
|
8482
9690
|
if (!item.timestamp && !exact) return null;
|
|
8483
|
-
return /* @__PURE__ */ jsx("p", { className: "text-2xs text-[var(--ds-text-muted)] mt-ds-0.5 tabular-nums", children: exact ? /* @__PURE__ */ jsxs("time", { dateTime: exact.iso, title: exact.text, children: [
|
|
8484
|
-
item.timestamp ?? exact.text,
|
|
8485
|
-
item.timestamp && /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
|
|
9691
|
+
return /* @__PURE__ */ jsx("p", { className: "text-2xs text-[var(--ds-text-muted)] mt-ds-0.5 tabular-nums", children: exact ? /* @__PURE__ */ jsxs("time", { dateTime: exact.iso, title: hydrated ? exact.text : void 0, children: [
|
|
9692
|
+
item.timestamp ?? (hydrated ? exact.text : "\xA0"),
|
|
9693
|
+
item.timestamp && hydrated && /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
|
|
8486
9694
|
" (",
|
|
8487
9695
|
exact.text,
|
|
8488
9696
|
")"
|
|
@@ -8515,10 +9723,10 @@ function Timeline({ items: allItems, orientation = "vertical", minItemWidth = 20
|
|
|
8515
9723
|
}, [ref]);
|
|
8516
9724
|
const fits = width === 0 || width >= items.length * minItemWidth;
|
|
8517
9725
|
const horizontal = orientation === "horizontal" || orientation === "responsive" && fits;
|
|
8518
|
-
const
|
|
8519
|
-
if (!pager) return
|
|
9726
|
+
const list2 = /* @__PURE__ */ jsx("div", { ref: setRefs, "data-ds-list": "", "data-timeline-orientation": horizontal ? "horizontal" : "vertical", className: pager ? void 0 : className, children: /* @__PURE__ */ jsx(RowsCtx, { value: true, children: horizontal ? /* @__PURE__ */ jsx(HorizontalLayout, { items, minItemWidth }) : /* @__PURE__ */ jsx(VerticalLayout, { items }) }) });
|
|
9727
|
+
if (!pager) return list2;
|
|
8520
9728
|
return /* @__PURE__ */ jsxs("div", { "data-gs-paged": "", className: cn("flex flex-col min-w-0", className), children: [
|
|
8521
|
-
|
|
9729
|
+
list2,
|
|
8522
9730
|
allItems.length > 0 && /* @__PURE__ */ jsx(Pagination, { ...pager.props })
|
|
8523
9731
|
] });
|
|
8524
9732
|
}
|
|
@@ -8733,8 +9941,8 @@ function TreeView({
|
|
|
8733
9941
|
);
|
|
8734
9942
|
const flatNodes = useCallback(() => {
|
|
8735
9943
|
const result = [];
|
|
8736
|
-
const walk = (
|
|
8737
|
-
for (const node of
|
|
9944
|
+
const walk = (list2, depth) => {
|
|
9945
|
+
for (const node of list2) {
|
|
8738
9946
|
result.push({ node, depth });
|
|
8739
9947
|
if (node.children && expanded.has(node.id)) walk(node.children, depth + 1);
|
|
8740
9948
|
}
|
|
@@ -9083,8 +10291,8 @@ function Carousel({
|
|
|
9083
10291
|
}
|
|
9084
10292
|
);
|
|
9085
10293
|
}
|
|
9086
|
-
function
|
|
9087
|
-
return d.toLocaleTimeString(
|
|
10294
|
+
function formatTime(d, locale) {
|
|
10295
|
+
return d.toLocaleTimeString(locale, { hour: "2-digit", minute: "2-digit" });
|
|
9088
10296
|
}
|
|
9089
10297
|
function isSameMinute(a, b) {
|
|
9090
10298
|
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate() && a.getHours() === b.getHours() && a.getMinutes() === b.getMinutes();
|
|
@@ -9164,6 +10372,9 @@ function SourcesRow({ sources }) {
|
|
|
9164
10372
|
}
|
|
9165
10373
|
var StreamingCaret = () => /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ml-ds-0.5 inline-block animate-pulse text-[var(--ds-accent-primary)]", children: "\u258D" });
|
|
9166
10374
|
var ChatMessageItem = memo(function ChatMessageItem2({ message: msg, grouped, spaced, layout, onAction, renderContent }) {
|
|
10375
|
+
const locale = useFormatLocale();
|
|
10376
|
+
const hydrated = useHydrated();
|
|
10377
|
+
const time = hydrated ? formatTime(msg.timestamp, locale) : "\xA0";
|
|
9167
10378
|
const streaming = msg.status === "streaming";
|
|
9168
10379
|
const content = renderContent ? renderContent(msg) : msg.content;
|
|
9169
10380
|
if (layout === "block") {
|
|
@@ -9178,7 +10389,7 @@ var ChatMessageItem = memo(function ChatMessageItem2({ message: msg, grouped, sp
|
|
|
9178
10389
|
!grouped && /* @__PURE__ */ jsxs("div", { className: "mb-ds-2 flex items-center gap-ds-2", children: [
|
|
9179
10390
|
!msg.isOwn && /* @__PURE__ */ jsx(SenderVisual, { sender: msg.sender }),
|
|
9180
10391
|
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-[var(--ds-text-secondary)]", children: msg.isOwn ? "You" : msg.sender.name }),
|
|
9181
|
-
/* @__PURE__ */ jsx("span", { className: "text-2xs text-[var(--ds-text-muted)]", children:
|
|
10392
|
+
/* @__PURE__ */ jsx("span", { className: "text-2xs text-[var(--ds-text-muted)]", children: time })
|
|
9182
10393
|
] }),
|
|
9183
10394
|
msg.status === "error" ? /* @__PURE__ */ jsx(Alert, { variant: "error", title: "Reply failed", children: typeof content === "string" && content ? content : void 0 }) : /* @__PURE__ */ jsx("div", { className: "space-y-ds-4 text-sm leading-relaxed text-[var(--ds-text-primary)]", children: typeof content === "string" ? /* @__PURE__ */ jsxs("p", { className: "whitespace-pre-wrap", children: [
|
|
9184
10395
|
content,
|
|
@@ -9218,7 +10429,7 @@ var ChatMessageItem = memo(function ChatMessageItem2({ message: msg, grouped, sp
|
|
|
9218
10429
|
]
|
|
9219
10430
|
}
|
|
9220
10431
|
),
|
|
9221
|
-
!grouped && /* @__PURE__ */ jsx("span", { className: "text-2xs text-[var(--ds-text-muted)] mt-ds-0.5 mx-ds-1", children:
|
|
10432
|
+
!grouped && /* @__PURE__ */ jsx("span", { className: "text-2xs text-[var(--ds-text-muted)] mt-ds-0.5 mx-ds-1", children: time }),
|
|
9222
10433
|
msg.sources && msg.sources.length > 0 && /* @__PURE__ */ jsx(SourcesRow, { sources: msg.sources }),
|
|
9223
10434
|
/* @__PURE__ */ jsx(ActionsRow, { message: msg, onAction })
|
|
9224
10435
|
] })
|
|
@@ -9248,7 +10459,7 @@ function ChatInputBar({ onSend, busy, onStop, onAttach, onVoice, placeholder })
|
|
|
9248
10459
|
className: cn(
|
|
9249
10460
|
"flex flex-col",
|
|
9250
10461
|
"rounded-[var(--ds-radius-lg)]",
|
|
9251
|
-
//
|
|
10462
|
+
// the composer is a field: its edge is every other control's resting edge (Sprint 25.14 A20, 25.19 K1)
|
|
9252
10463
|
"border-[length:var(--ds-border-width)] border-[var(--ds-input-border)]",
|
|
9253
10464
|
"bg-[var(--ds-input-bg)]",
|
|
9254
10465
|
"shadow-[var(--ds-input-shadow)]",
|
|
@@ -9526,12 +10737,12 @@ function apply(target, corner) {
|
|
|
9526
10737
|
}
|
|
9527
10738
|
function claimCornerInset(corner, inset, priority, target) {
|
|
9528
10739
|
const claim = { inset, priority, seq: ++seq };
|
|
9529
|
-
const
|
|
9530
|
-
|
|
10740
|
+
const list2 = claimsFor(target)[corner];
|
|
10741
|
+
list2.push(claim);
|
|
9531
10742
|
apply(target, corner);
|
|
9532
10743
|
return () => {
|
|
9533
|
-
const i =
|
|
9534
|
-
if (i >= 0)
|
|
10744
|
+
const i = list2.indexOf(claim);
|
|
10745
|
+
if (i >= 0) list2.splice(i, 1);
|
|
9535
10746
|
apply(target, corner);
|
|
9536
10747
|
};
|
|
9537
10748
|
}
|
|
@@ -9865,7 +11076,7 @@ var StackedList = forwardRef(function StackedList2({
|
|
|
9865
11076
|
const stackMeta = isPhone && articles;
|
|
9866
11077
|
const selectable = selectedId !== void 0 || items.some((i) => i.selected !== void 0);
|
|
9867
11078
|
const inset = articles ? inCard ? "px-ds-5" : "px-0" : inCard ? "px-ds-5" : inPane ? "pl-ds-3 pr-ds-4" : selectable ? "pl-ds-3 pr-0" : "px-0";
|
|
9868
|
-
const
|
|
11079
|
+
const list2 = /* @__PURE__ */ jsx(
|
|
9869
11080
|
"ul",
|
|
9870
11081
|
{
|
|
9871
11082
|
ref,
|
|
@@ -9967,12 +11178,14 @@ var StackedList = forwardRef(function StackedList2({
|
|
|
9967
11178
|
}) })
|
|
9968
11179
|
}
|
|
9969
11180
|
);
|
|
9970
|
-
if (!pager) return
|
|
11181
|
+
if (!pager) return list2;
|
|
9971
11182
|
return /* @__PURE__ */ jsxs("div", { "data-gs-paged": "", className: cn("flex flex-col min-w-0", className), children: [
|
|
9972
|
-
|
|
11183
|
+
list2,
|
|
9973
11184
|
items.length > 0 && /* @__PURE__ */ jsx(Pagination, { ...pager.props })
|
|
9974
11185
|
] });
|
|
9975
11186
|
});
|
|
11187
|
+
|
|
11188
|
+
// ../../showcase/src/lib/time-days.ts
|
|
9976
11189
|
var TIME_ZOOMS = ["day", "week", "month", "quarter"];
|
|
9977
11190
|
var DAY_MS2 = 864e5;
|
|
9978
11191
|
var DATE_ONLY2 = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
@@ -9999,9 +11212,15 @@ function dayOf(value) {
|
|
|
9999
11212
|
return back.getUTCFullYear() === y && back.getUTCMonth() === mo && back.getUTCDate() === d ? day : NaN;
|
|
10000
11213
|
}
|
|
10001
11214
|
function dateOfDay(day) {
|
|
10002
|
-
const
|
|
10003
|
-
const u = new Date(
|
|
10004
|
-
return new Date(u.getUTCFullYear(), u.getUTCMonth(), u.getUTCDate(), 0, 0, 0, Math.round((day -
|
|
11215
|
+
const whole2 = Math.floor(day);
|
|
11216
|
+
const u = new Date(whole2 * DAY_MS2);
|
|
11217
|
+
return new Date(u.getUTCFullYear(), u.getUTCMonth(), u.getUTCDate(), 0, 0, 0, Math.round((day - whole2) * DAY_MS2));
|
|
11218
|
+
}
|
|
11219
|
+
function isZoned(value) {
|
|
11220
|
+
if (value instanceof Date) return !Number.isNaN(value.getTime());
|
|
11221
|
+
if (typeof value !== "string") return false;
|
|
11222
|
+
const text = value.trim();
|
|
11223
|
+
return !DATE_ONLY2.test(text) && !Number.isNaN(new Date(text).getTime());
|
|
10005
11224
|
}
|
|
10006
11225
|
function isWholeDay(value) {
|
|
10007
11226
|
return typeof value === "string" ? DATE_ONLY2.test(value.trim()) : Number.isInteger(dayOf(value));
|
|
@@ -10013,6 +11232,60 @@ function endDayOf(value) {
|
|
|
10013
11232
|
function rangeEnd(start, end) {
|
|
10014
11233
|
return end instanceof Date && !isWholeDay(start) ? dayOf(end) : endDayOf(end);
|
|
10015
11234
|
}
|
|
11235
|
+
var formats2 = localeCache(128);
|
|
11236
|
+
function dayFormatter(given, options) {
|
|
11237
|
+
const locale = given ?? formatLocale();
|
|
11238
|
+
return formats2(`${locale ?? ""}|${JSON.stringify(options)}`, () => new Intl.DateTimeFormat(locale, { ...options, timeZone: "UTC" }));
|
|
11239
|
+
}
|
|
11240
|
+
function timeExtent(ranges) {
|
|
11241
|
+
let start = Infinity;
|
|
11242
|
+
let end = -Infinity;
|
|
11243
|
+
for (const r of ranges) {
|
|
11244
|
+
if (r == null) continue;
|
|
11245
|
+
const s = dayOf(r.start);
|
|
11246
|
+
const e = r.end == null ? endDayOf(r.start) : rangeEnd(r.start, r.end);
|
|
11247
|
+
if (Number.isFinite(s)) start = Math.min(start, s);
|
|
11248
|
+
if (Number.isFinite(e)) end = Math.max(end, e);
|
|
11249
|
+
}
|
|
11250
|
+
return Number.isFinite(start) && Number.isFinite(end) ? { start, end: Math.max(start, end) } : { start: NaN, end: NaN };
|
|
11251
|
+
}
|
|
11252
|
+
var DAY_WORDS = { day: "numeric", month: "long" };
|
|
11253
|
+
var TIME_WORDS = { hour: "2-digit", minute: "2-digit" };
|
|
11254
|
+
var SEPARATOR = /\s*[\u2010-\u2015\u2212~\uff5e\u301c-]\s*/;
|
|
11255
|
+
var english = (f) => new Intl.Locale(f.resolvedOptions().locale).language === "en";
|
|
11256
|
+
function range(f, a, b, to) {
|
|
11257
|
+
if (typeof f.formatRangeToParts !== "function") return to === void 0 ? f.formatRange(a, b) : `${f.format(a)}${to}${f.format(b)}`;
|
|
11258
|
+
const parts = f.formatRangeToParts(a, b);
|
|
11259
|
+
const lastOfStart = parts.map((p) => p.source).lastIndexOf("startRange");
|
|
11260
|
+
const firstOfEnd = parts.findIndex((p) => p.source === "endRange");
|
|
11261
|
+
if (lastOfStart < 0 || firstOfEnd < 0) return f.format(a);
|
|
11262
|
+
if (to === void 0) return parts.map((p) => p.value).join("");
|
|
11263
|
+
let joined = false;
|
|
11264
|
+
const out = parts.map((p, i) => {
|
|
11265
|
+
if (joined || i <= lastOfStart || i >= firstOfEnd || !SEPARATOR.test(p.value)) return p.value;
|
|
11266
|
+
joined = true;
|
|
11267
|
+
return p.value.replace(SEPARATOR, to);
|
|
11268
|
+
});
|
|
11269
|
+
if (!joined) out.splice(lastOfStart + 1, 0, to);
|
|
11270
|
+
return out.join("");
|
|
11271
|
+
}
|
|
11272
|
+
function formatDateRange(start, end, words) {
|
|
11273
|
+
const { locale, to, day = DAY_WORDS, time = TIME_WORDS } = words ?? {};
|
|
11274
|
+
const until = end ?? start;
|
|
11275
|
+
const from = dayOf(start);
|
|
11276
|
+
const stop = rangeEnd(start, until);
|
|
11277
|
+
if (!Number.isFinite(from) || !Number.isFinite(stop)) return "";
|
|
11278
|
+
const timed = !isWholeDay(start) || !isWholeDay(until);
|
|
11279
|
+
const first = timed ? from : Math.floor(from);
|
|
11280
|
+
const last2 = timed ? Math.max(from, stop) : Math.max(first, Math.ceil(stop) - 1);
|
|
11281
|
+
const a = new Date(first * DAY_MS2);
|
|
11282
|
+
const b = new Date(last2 * DAY_MS2);
|
|
11283
|
+
const years = a.getUTCFullYear() !== b.getUTCFullYear() && day.year === void 0;
|
|
11284
|
+
const f = dayFormatter(locale, { ...day, ...years ? { year: "numeric" } : {}, ...timed ? time : {} });
|
|
11285
|
+
return first === last2 ? f.format(a) : range(f, a, b, to ?? (english(f) ? " to " : void 0));
|
|
11286
|
+
}
|
|
11287
|
+
|
|
11288
|
+
// ../../showcase/src/lib/time-scale.ts
|
|
10016
11289
|
var MINOR = { day: "day", week: "week", month: "month", quarter: "quarter" };
|
|
10017
11290
|
var MAJOR = { day: "month", week: "month", month: "year", quarter: "year" };
|
|
10018
11291
|
var weekday = (day) => (day % 7 + 7 + 4) % 7;
|
|
@@ -10037,19 +11310,8 @@ function periodAfter(unit, start) {
|
|
|
10037
11310
|
if (unit === "quarter") return utcDay(y, m + 3, 1);
|
|
10038
11311
|
return utcDay(y + 1, 0, 1);
|
|
10039
11312
|
}
|
|
10040
|
-
|
|
10041
|
-
|
|
10042
|
-
const locale = given ?? formatLocale();
|
|
10043
|
-
const key = `${locale ?? ""}|${JSON.stringify(options)}`;
|
|
10044
|
-
let f = formats.get(key);
|
|
10045
|
-
if (!f) {
|
|
10046
|
-
f = new Intl.DateTimeFormat(locale, { ...options, timeZone: "UTC" });
|
|
10047
|
-
formats.set(key, f);
|
|
10048
|
-
}
|
|
10049
|
-
return f;
|
|
10050
|
-
}
|
|
10051
|
-
function format(day, locale, options) {
|
|
10052
|
-
return formatter(locale, options).format(new Date(day * DAY_MS2));
|
|
11313
|
+
function format2(day, locale, options) {
|
|
11314
|
+
return dayFormatter(locale, options).format(new Date(day * DAY_MS2));
|
|
10053
11315
|
}
|
|
10054
11316
|
var pad22 = (n) => String(n).padStart(2, "0");
|
|
10055
11317
|
function keyOf(unit, day) {
|
|
@@ -10062,7 +11324,7 @@ function keyOf(unit, day) {
|
|
|
10062
11324
|
return `${y}-${pad22(m + 1)}-${pad22(u.getUTCDate())}`;
|
|
10063
11325
|
}
|
|
10064
11326
|
function labelsOf(unit, role, day, locale) {
|
|
10065
|
-
const f = (options) =>
|
|
11327
|
+
const f = (options) => format2(day, locale, options);
|
|
10066
11328
|
let forms;
|
|
10067
11329
|
if (unit === "day") forms = [f({ weekday: "short", day: "numeric" }), f({ day: "numeric" })];
|
|
10068
11330
|
else if (unit === "week") forms = [f({ day: "numeric", month: "short" }), f({ day: "numeric" })];
|
|
@@ -10122,7 +11384,7 @@ function build(s) {
|
|
|
10122
11384
|
return scale;
|
|
10123
11385
|
}
|
|
10124
11386
|
var toMinute = (day) => Math.floor(day * 1440 + 1e-6) / 1440;
|
|
10125
|
-
function scaleOver(from, to, zoom, todayValue, weekStartsOn, locale, pxPerDay,
|
|
11387
|
+
function scaleOver(from, to, zoom, todayValue, weekStartsOn, locale, pxPerDay, pad4) {
|
|
10126
11388
|
const fallback = Number.isFinite(todayValue) ? Math.floor(todayValue) : 0;
|
|
10127
11389
|
const a = Number.isFinite(from) ? from : fallback;
|
|
10128
11390
|
const b = Number.isFinite(to) ? to : Math.floor(a) + 1;
|
|
@@ -10131,7 +11393,7 @@ function scaleOver(from, to, zoom, todayValue, weekStartsOn, locale, pxPerDay, p
|
|
|
10131
11393
|
const unit = MINOR[zoom];
|
|
10132
11394
|
let startDay = periodStart(unit, lo, weekStartsOn);
|
|
10133
11395
|
let endDay = periodAfter(unit, periodStart(unit, hi - 1, weekStartsOn));
|
|
10134
|
-
for (let i = 0; i <
|
|
11396
|
+
for (let i = 0; i < pad4; i++) {
|
|
10135
11397
|
startDay = periodStart(unit, startDay - 1, weekStartsOn);
|
|
10136
11398
|
endDay = periodAfter(unit, endDay);
|
|
10137
11399
|
}
|
|
@@ -10140,8 +11402,8 @@ function scaleOver(from, to, zoom, todayValue, weekStartsOn, locale, pxPerDay, p
|
|
|
10140
11402
|
function extendedEnd(scale, width) {
|
|
10141
11403
|
if (!(width > scale.width) || !(scale.pxPerDay > 0)) return scale.endDay;
|
|
10142
11404
|
const unit = MINOR[scale.zoom];
|
|
10143
|
-
const
|
|
10144
|
-
return periodAfter(unit, periodStart(unit,
|
|
11405
|
+
const last2 = scale.startDay + Math.ceil(width / scale.pxPerDay) - 1;
|
|
11406
|
+
return periodAfter(unit, periodStart(unit, last2, scale.weekStartsOn));
|
|
10145
11407
|
}
|
|
10146
11408
|
function extendTimeScaleTo(scale, endDay) {
|
|
10147
11409
|
if (!(endDay > scale.endDay)) return scale;
|
|
@@ -10154,7 +11416,10 @@ var noSubscription = () => () => {
|
|
|
10154
11416
|
};
|
|
10155
11417
|
var inBrowser2 = () => true;
|
|
10156
11418
|
var onServer2 = () => false;
|
|
10157
|
-
function useTimeScale({ start, end, zoom, today, weekStartsOn
|
|
11419
|
+
function useTimeScale({ start, end, zoom, today, weekStartsOn: own, locale: ownLocale, pxPerDay, pad: pad4 = 0 }) {
|
|
11420
|
+
const weekStartsOn = useWeekStart(own, ownLocale);
|
|
11421
|
+
const pageLocale = useFormatLocale();
|
|
11422
|
+
const locale = ownLocale ?? pageLocale;
|
|
10158
11423
|
const readable = useSyncExternalStore(noSubscription, inBrowser2, onServer2);
|
|
10159
11424
|
const [mounted] = useState(() => toMinute(dayOf(/* @__PURE__ */ new Date())));
|
|
10160
11425
|
const pending = today === void 0 && !readable;
|
|
@@ -10163,57 +11428,10 @@ function useTimeScale({ start, end, zoom, today, weekStartsOn = 1, locale, pxPer
|
|
|
10163
11428
|
const todayValue = today !== void 0 ? toMinute(dayOf(today)) : pending ? NaN : mounted;
|
|
10164
11429
|
const density = pxPerDay?.[zoom] ?? DENSITY[zoom];
|
|
10165
11430
|
return useMemo(() => {
|
|
10166
|
-
const scale = scaleOver(from, to, zoom, todayValue, weekStartsOn, locale, density,
|
|
11431
|
+
const scale = scaleOver(from, to, zoom, todayValue, weekStartsOn, locale, density, pad4);
|
|
10167
11432
|
if (pending) awaiting.add(scale);
|
|
10168
11433
|
return scale;
|
|
10169
|
-
}, [from, to, zoom, todayValue, weekStartsOn, locale, density,
|
|
10170
|
-
}
|
|
10171
|
-
function timeExtent(ranges) {
|
|
10172
|
-
let start = Infinity;
|
|
10173
|
-
let end = -Infinity;
|
|
10174
|
-
for (const r of ranges) {
|
|
10175
|
-
if (r == null) continue;
|
|
10176
|
-
const s = dayOf(r.start);
|
|
10177
|
-
const e = r.end == null ? endDayOf(r.start) : rangeEnd(r.start, r.end);
|
|
10178
|
-
if (Number.isFinite(s)) start = Math.min(start, s);
|
|
10179
|
-
if (Number.isFinite(e)) end = Math.max(end, e);
|
|
10180
|
-
}
|
|
10181
|
-
return Number.isFinite(start) && Number.isFinite(end) ? { start, end: Math.max(start, end) } : { start: NaN, end: NaN };
|
|
10182
|
-
}
|
|
10183
|
-
var DAY_WORDS = { day: "numeric", month: "long" };
|
|
10184
|
-
var TIME_WORDS = { hour: "2-digit", minute: "2-digit" };
|
|
10185
|
-
var SEPARATOR = /\s*[\u2010-\u2015\u2212~\uff5e\u301c-]\s*/;
|
|
10186
|
-
var english = (f) => new Intl.Locale(f.resolvedOptions().locale).language === "en";
|
|
10187
|
-
function range(f, a, b, to) {
|
|
10188
|
-
if (typeof f.formatRangeToParts !== "function") return to === void 0 ? f.formatRange(a, b) : `${f.format(a)}${to}${f.format(b)}`;
|
|
10189
|
-
const parts = f.formatRangeToParts(a, b);
|
|
10190
|
-
const lastOfStart = parts.map((p) => p.source).lastIndexOf("startRange");
|
|
10191
|
-
const firstOfEnd = parts.findIndex((p) => p.source === "endRange");
|
|
10192
|
-
if (lastOfStart < 0 || firstOfEnd < 0) return f.format(a);
|
|
10193
|
-
if (to === void 0) return parts.map((p) => p.value).join("");
|
|
10194
|
-
let joined = false;
|
|
10195
|
-
const out = parts.map((p, i) => {
|
|
10196
|
-
if (joined || i <= lastOfStart || i >= firstOfEnd || !SEPARATOR.test(p.value)) return p.value;
|
|
10197
|
-
joined = true;
|
|
10198
|
-
return p.value.replace(SEPARATOR, to);
|
|
10199
|
-
});
|
|
10200
|
-
if (!joined) out.splice(lastOfStart + 1, 0, to);
|
|
10201
|
-
return out.join("");
|
|
10202
|
-
}
|
|
10203
|
-
function formatDateRange(start, end, words) {
|
|
10204
|
-
const { locale, to, day = DAY_WORDS, time = TIME_WORDS } = words ?? {};
|
|
10205
|
-
const until = end ?? start;
|
|
10206
|
-
const from = dayOf(start);
|
|
10207
|
-
const stop = rangeEnd(start, until);
|
|
10208
|
-
if (!Number.isFinite(from) || !Number.isFinite(stop)) return "";
|
|
10209
|
-
const timed = !isWholeDay(start) || !isWholeDay(until);
|
|
10210
|
-
const first = timed ? from : Math.floor(from);
|
|
10211
|
-
const last = timed ? Math.max(from, stop) : Math.max(first, Math.ceil(stop) - 1);
|
|
10212
|
-
const a = new Date(first * DAY_MS2);
|
|
10213
|
-
const b = new Date(last * DAY_MS2);
|
|
10214
|
-
const years = a.getUTCFullYear() !== b.getUTCFullYear() && day.year === void 0;
|
|
10215
|
-
const f = formatter(locale, { ...day, ...years ? { year: "numeric" } : {}, ...timed ? time : {} });
|
|
10216
|
-
return first === last ? f.format(a) : range(f, a, b, to ?? (english(f) ? " to " : void 0));
|
|
11434
|
+
}, [from, to, zoom, todayValue, weekStartsOn, locale, density, pad4, pending]);
|
|
10217
11435
|
}
|
|
10218
11436
|
function createScrollStore() {
|
|
10219
11437
|
let current = { scrollLeft: 0, visibleWidth: 0 };
|
|
@@ -10334,11 +11552,11 @@ function measurer(info) {
|
|
|
10334
11552
|
return v;
|
|
10335
11553
|
};
|
|
10336
11554
|
}
|
|
10337
|
-
function useTextMeasure(ref) {
|
|
11555
|
+
function useTextMeasure(ref, active = true) {
|
|
10338
11556
|
const [info, setInfo] = useState(null);
|
|
10339
11557
|
useLayoutEffect(() => {
|
|
10340
11558
|
const el = ref.current;
|
|
10341
|
-
if (!el) return;
|
|
11559
|
+
if (!active || !el) return;
|
|
10342
11560
|
let live = true;
|
|
10343
11561
|
const read = (fresh) => {
|
|
10344
11562
|
if (!live) return;
|
|
@@ -10358,7 +11576,7 @@ function useTextMeasure(ref) {
|
|
|
10358
11576
|
ro?.disconnect();
|
|
10359
11577
|
fonts?.removeEventListener?.("loadingdone", loaded);
|
|
10360
11578
|
};
|
|
10361
|
-
}, [ref]);
|
|
11579
|
+
}, [ref, active]);
|
|
10362
11580
|
return useMemo(() => measurer(info), [info]);
|
|
10363
11581
|
}
|
|
10364
11582
|
var fontGeneration = 0;
|
|
@@ -10449,6 +11667,7 @@ function TimeScaleHeader({ todayLabel = "Today", className }) {
|
|
|
10449
11667
|
const todayRef = useRef(null);
|
|
10450
11668
|
const measured = visibleWidth > 0;
|
|
10451
11669
|
const view = { start: scrollLeft, end: scrollLeft + visibleWidth };
|
|
11670
|
+
const hydrated = useHydrated();
|
|
10452
11671
|
const major = useFittedLabels(scale.major, majorRef, measured ? { visible: view } : {});
|
|
10453
11672
|
const minor = useFittedLabels(scale.minor, minorRef, measured ? { align: "center", visible: view } : { align: "center" });
|
|
10454
11673
|
const measureToday = useTextMeasure(todayRef);
|
|
@@ -10461,12 +11680,12 @@ function TimeScaleHeader({ todayLabel = "Today", className }) {
|
|
|
10461
11680
|
/* @__PURE__ */ jsxs("div", { "data-scale-row": "major", className: "relative h-7 font-medium text-[var(--ds-text-primary)]", children: [
|
|
10462
11681
|
/* @__PURE__ */ jsx("span", { ref: majorRef, className: "invisible absolute whitespace-nowrap leading-none", children: "0" }),
|
|
10463
11682
|
scale.major.slice(1).map((t) => /* @__PURE__ */ jsx("span", { className: "absolute inset-y-0 border-s-[length:1px] border-[var(--ds-border-subtle)]", style: { insetInlineStart: t.x } }, `line-${t.key}`)),
|
|
10464
|
-
major.map((l) => l.text && /* @__PURE__ */ jsx("span", { "data-scale-label": "", className: "absolute top-1/2 -translate-y-1/2 whitespace-nowrap leading-none", style: { insetInlineStart: l.x }, children: l.text }, l.key))
|
|
11683
|
+
hydrated && major.map((l) => l.text && /* @__PURE__ */ jsx("span", { "data-scale-label": "", className: "absolute top-1/2 -translate-y-1/2 whitespace-nowrap leading-none", style: { insetInlineStart: l.x }, children: l.text }, l.key))
|
|
10465
11684
|
] }),
|
|
10466
11685
|
/* @__PURE__ */ jsxs("div", { "data-scale-row": "minor", className: "relative h-7 border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] text-[var(--ds-text-secondary)]", children: [
|
|
10467
11686
|
/* @__PURE__ */ jsx("span", { ref: minorRef, className: "invisible absolute whitespace-nowrap leading-none tabular-nums", children: "0" }),
|
|
10468
11687
|
scale.minor.slice(1).map((t) => /* @__PURE__ */ jsx("span", { className: "absolute inset-y-0 border-s-[length:1px] border-[var(--ds-border-subtle)]", style: { insetInlineStart: t.x } }, `line-${t.key}`)),
|
|
10469
|
-
minor.map((l) => l.text && !underToday(l.x, l.width) && /* @__PURE__ */ jsx("span", { "data-scale-label": "", className: "absolute top-1/2 -translate-y-1/2 whitespace-nowrap leading-none tabular-nums", style: { insetInlineStart: l.x }, children: l.text }, l.key)),
|
|
11688
|
+
hydrated && minor.map((l) => l.text && !underToday(l.x, l.width) && /* @__PURE__ */ jsx("span", { "data-scale-label": "", className: "absolute top-1/2 -translate-y-1/2 whitespace-nowrap leading-none tabular-nums", style: { insetInlineStart: l.x }, children: l.text }, l.key)),
|
|
10470
11689
|
/* @__PURE__ */ jsx(
|
|
10471
11690
|
"span",
|
|
10472
11691
|
{
|
|
@@ -10643,8 +11862,8 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
10643
11862
|
if (shadeDays && drawn.pxPerDay >= SHADE_MIN) {
|
|
10644
11863
|
for (let d = drawn.startDay; d < drawn.endDay; d++) {
|
|
10645
11864
|
if (!shadeDays(calendarDay(d))) continue;
|
|
10646
|
-
const
|
|
10647
|
-
if (
|
|
11865
|
+
const last2 = shaded[shaded.length - 1];
|
|
11866
|
+
if (last2 && Math.abs(last2.x + last2.width - drawn.x(d)) < 0.5) last2.width += drawn.pxPerDay;
|
|
10648
11867
|
else shaded.push({ key: String(d), x: drawn.x(d), width: drawn.pxPerDay });
|
|
10649
11868
|
}
|
|
10650
11869
|
}
|
|
@@ -10771,6 +11990,7 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
10771
11990
|
ref: scrollerRef,
|
|
10772
11991
|
role: "region",
|
|
10773
11992
|
"aria-label": ariaLabel,
|
|
11993
|
+
suppressHydrationWarning: true,
|
|
10774
11994
|
tabIndex: tabStop ? 0 : void 0,
|
|
10775
11995
|
onScroll,
|
|
10776
11996
|
className: "peer h-full overflow-auto isolate outline-none",
|
|
@@ -10875,6 +12095,10 @@ function TimeBar({ start, end, minWidth = 0, labels, children, className, style,
|
|
|
10875
12095
|
}
|
|
10876
12096
|
);
|
|
10877
12097
|
}
|
|
12098
|
+
function LocaleProvider({ lang, acceptLanguage, children }) {
|
|
12099
|
+
const value = useMemo(() => localeChoice(lang, acceptLanguage), [lang, acceptLanguage]);
|
|
12100
|
+
return /* @__PURE__ */ jsx(LocaleContext.Provider, { value, children });
|
|
12101
|
+
}
|
|
10878
12102
|
|
|
10879
12103
|
// ../../showcase/src/lib/gantt-layout.ts
|
|
10880
12104
|
var ROW_HEIGHT2 = 40;
|
|
@@ -10895,18 +12119,18 @@ function datesOf(item) {
|
|
|
10895
12119
|
const end = asDate(item.end);
|
|
10896
12120
|
return end !== void 0 && Number.isFinite(endDayOf(end)) ? { start, end } : null;
|
|
10897
12121
|
}
|
|
10898
|
-
function uniqueById(
|
|
12122
|
+
function uniqueById(list2) {
|
|
10899
12123
|
const seen = /* @__PURE__ */ new Set();
|
|
10900
12124
|
const repeated = /* @__PURE__ */ new Set();
|
|
10901
12125
|
const unique = [];
|
|
10902
|
-
for (const entry of
|
|
12126
|
+
for (const entry of list2) {
|
|
10903
12127
|
if (seen.has(entry.id)) repeated.add(entry.id);
|
|
10904
12128
|
else {
|
|
10905
12129
|
seen.add(entry.id);
|
|
10906
12130
|
unique.push(entry);
|
|
10907
12131
|
}
|
|
10908
12132
|
}
|
|
10909
|
-
return repeated.size ? { unique, repeated: [...repeated] } : { unique:
|
|
12133
|
+
return repeated.size ? { unique, repeated: [...repeated] } : { unique: list2, repeated: [] };
|
|
10910
12134
|
}
|
|
10911
12135
|
function ganttRows(items, groups, collapsed) {
|
|
10912
12136
|
const known = new Set(groups.map((g) => g.id));
|
|
@@ -10917,8 +12141,8 @@ function ganttRows(items, groups, collapsed) {
|
|
|
10917
12141
|
loose.push(item);
|
|
10918
12142
|
continue;
|
|
10919
12143
|
}
|
|
10920
|
-
const
|
|
10921
|
-
if (
|
|
12144
|
+
const list2 = byGroup.get(item.group);
|
|
12145
|
+
if (list2) list2.push(item);
|
|
10922
12146
|
else byGroup.set(item.group, [item]);
|
|
10923
12147
|
}
|
|
10924
12148
|
const shown = groups.filter((g) => byGroup.has(g.id));
|
|
@@ -10988,8 +12212,8 @@ function ganttArrows(items, rows, shapeOf, collapsed) {
|
|
|
10988
12212
|
}
|
|
10989
12213
|
return arrows;
|
|
10990
12214
|
}
|
|
10991
|
-
function labelPlace(shape, textWidth, scaleWidth, { pad:
|
|
10992
|
-
if (shape.kind === "bar" && textWidth + 2 *
|
|
12215
|
+
function labelPlace(shape, textWidth, scaleWidth, { pad: pad4 = 8, gap = BESIDE } = {}) {
|
|
12216
|
+
if (shape.kind === "bar" && textWidth + 2 * pad4 <= shape.x1 - shape.x0) return "inside";
|
|
10993
12217
|
if (shape.x1 + gap + textWidth <= scaleWidth) return "after";
|
|
10994
12218
|
return shape.x0 - gap - textWidth >= 0 ? "before" : "after";
|
|
10995
12219
|
}
|
|
@@ -11121,6 +12345,11 @@ function Gantt({
|
|
|
11121
12345
|
if (phases.repeated.length) warnOnce2(`more than one group has the id ${quoted(phases.repeated)}; only the first of each is shown.`);
|
|
11122
12346
|
}, [plan, phases]);
|
|
11123
12347
|
const tasks = plan.unique;
|
|
12348
|
+
const pageLocale = useFormatLocale();
|
|
12349
|
+
const writeLocale = locale ?? pageLocale;
|
|
12350
|
+
const hydrated = useHydrated();
|
|
12351
|
+
const zoned = useMemo(() => isZoned(today) || tasks.some((t) => isZoned(t.start) || isZoned(t.end)), [tasks, today]);
|
|
12352
|
+
const pending = zoned && !hydrated;
|
|
11124
12353
|
const extent = useMemo(() => itemsExtent(tasks), [tasks]);
|
|
11125
12354
|
const scale = useTimeScale({ start: extent.start, end: extent.end, zoom, today, weekStartsOn, locale, pad: 1 });
|
|
11126
12355
|
const rows = useMemo(() => ganttRows(tasks, phases.unique, collapsed), [tasks, phases, collapsed]);
|
|
@@ -11130,7 +12359,7 @@ function Gantt({
|
|
|
11130
12359
|
const byKey = useMemo(() => new Map(rows.map((r) => [r.key, r])), [rows]);
|
|
11131
12360
|
const names = useMemo(() => {
|
|
11132
12361
|
const byId = new Map(tasks.map((i) => [i.id, i]));
|
|
11133
|
-
const
|
|
12362
|
+
const list2 = new Intl.ListFormat(writeLocale, { type: "conjunction" });
|
|
11134
12363
|
const out = /* @__PURE__ */ new Map();
|
|
11135
12364
|
for (const item of tasks) {
|
|
11136
12365
|
const dates = datesOf(item);
|
|
@@ -11139,29 +12368,29 @@ function Gantt({
|
|
|
11139
12368
|
out.set(itemKey(item.id), [
|
|
11140
12369
|
item.title,
|
|
11141
12370
|
item.milestone ? "milestone" : null,
|
|
11142
|
-
dates ? formatDateRange(dates.start, dates.end, { locale }) : NO_DATES,
|
|
12371
|
+
dates ? formatDateRange(dates.start, dates.end, { locale: writeLocale }) : NO_DATES,
|
|
11143
12372
|
status?.label ?? null,
|
|
11144
|
-
after.length ? `after ${
|
|
12373
|
+
after.length ? `after ${list2.format(after)}` : null
|
|
11145
12374
|
].filter((part) => part).join(", "));
|
|
11146
12375
|
}
|
|
11147
12376
|
for (const row of rows) {
|
|
11148
12377
|
if (!row.group || !row.children) continue;
|
|
11149
12378
|
const e = extents.get(row.group.id);
|
|
11150
12379
|
const count = row.children.length === 1 ? "1 item" : `${row.children.length} items`;
|
|
11151
|
-
const span = Number.isFinite(e.start) ? formatDateRange(e.start, e.end, { locale }) : NO_DATES;
|
|
12380
|
+
const span = Number.isFinite(e.start) ? formatDateRange(e.start, e.end, { locale: writeLocale }) : NO_DATES;
|
|
11152
12381
|
out.set(row.key, [row.group.title, span, count].filter((part) => part).join(", "));
|
|
11153
12382
|
}
|
|
11154
12383
|
return out;
|
|
11155
|
-
}, [tasks, rows, extents, statuses,
|
|
12384
|
+
}, [tasks, rows, extents, statuses, writeLocale]);
|
|
11156
12385
|
const nameOf = (row) => {
|
|
11157
12386
|
const name = names.get(row.key) ?? "";
|
|
11158
12387
|
const words = row.item && describe ? describe(row.item) : "";
|
|
11159
12388
|
return words ? `${name}, ${words}` : name;
|
|
11160
12389
|
};
|
|
11161
12390
|
const regionLabel = useMemo(() => {
|
|
11162
|
-
const span = Number.isFinite(extent.start) ? formatDateRange(extent.start, extent.end, { locale }) : "";
|
|
12391
|
+
const span = Number.isFinite(extent.start) ? formatDateRange(extent.start, extent.end, { locale: writeLocale }) : "";
|
|
11163
12392
|
return `${ariaLabel}, ${span || NO_DATES}`;
|
|
11164
|
-
}, [ariaLabel, extent,
|
|
12393
|
+
}, [ariaLabel, extent, writeLocale]);
|
|
11165
12394
|
const hasStatuses = useMemo(() => Object.keys(statuses).length > 0, [statuses]);
|
|
11166
12395
|
const toneOf = (item) => {
|
|
11167
12396
|
const status = item.status === void 0 ? void 0 : statuses[item.status];
|
|
@@ -11169,7 +12398,7 @@ function Gantt({
|
|
|
11169
12398
|
return { tone, cue: hasStatuses ? status?.icon ?? tone.icon : void 0 };
|
|
11170
12399
|
};
|
|
11171
12400
|
const probeRef = useRef(null);
|
|
11172
|
-
const measure = useTextMeasure(probeRef);
|
|
12401
|
+
const measure = useTextMeasure(probeRef, !pending);
|
|
11173
12402
|
const treeRef = useRef(null);
|
|
11174
12403
|
const viewportRef = useRef(null);
|
|
11175
12404
|
const [activeState, setActive] = useState(null);
|
|
@@ -11280,6 +12509,9 @@ function Gantt({
|
|
|
11280
12509
|
"aria-setsize": row.setSize,
|
|
11281
12510
|
"aria-posinset": row.posInSet,
|
|
11282
12511
|
"aria-label": nameOf(row),
|
|
12512
|
+
// a plan of days is named on the server too: the same dates, which the server's date data and the browser's can write
|
|
12513
|
+
// a space apart ("5–9 Oct", "5 – 9 Oct"), so hydrating keeps the server's name (Sprint 25.20's review)
|
|
12514
|
+
suppressHydrationWarning: true,
|
|
11283
12515
|
"data-grid-key": row.key,
|
|
11284
12516
|
tabIndex: grid.tabIndexOf(row.key),
|
|
11285
12517
|
onFocus: () => {
|
|
@@ -11381,7 +12613,8 @@ function Gantt({
|
|
|
11381
12613
|
const legend = /* @__PURE__ */ jsx(Legend, { statuses });
|
|
11382
12614
|
const legendApart = toolbar === false && hasStatuses;
|
|
11383
12615
|
const apartRef = useRef(null);
|
|
11384
|
-
const apartFill = useFillHeight(apartRef, legendApart);
|
|
12616
|
+
const apartFill = useFillHeight(apartRef, legendApart && !pending);
|
|
12617
|
+
if (pending) return /* @__PURE__ */ jsx("div", { "aria-busy": "true", "data-gantt-pending": "", className: cn(className), style: { minHeight: rows.length * ROW_HEIGHT2 + 96 } });
|
|
11385
12618
|
const chart = /* @__PURE__ */ jsx(
|
|
11386
12619
|
TimeViewport,
|
|
11387
12620
|
{
|
|
@@ -12174,6 +13407,7 @@ function Stepper({ steps, currentStep, onStepChange, orientation = "horizontal",
|
|
|
12174
13407
|
const tabRow = useHeaderTabRow();
|
|
12175
13408
|
const narrow = useNarrowRow(tabRow?.row ?? null);
|
|
12176
13409
|
const inHeader = isHorizontal && tabRow != null;
|
|
13410
|
+
const kindOf2 = (step) => !onStepChange ? "progress" : step.disabled ? "locked" : "open";
|
|
12177
13411
|
if (inHeader && narrow) {
|
|
12178
13412
|
const current = steps[currentStep];
|
|
12179
13413
|
const where = `Step ${Math.min(currentStep + 1, steps.length)} of ${steps.length}`;
|
|
@@ -12198,12 +13432,12 @@ function Stepper({ steps, currentStep, onStepChange, orientation = "horizontal",
|
|
|
12198
13432
|
] });
|
|
12199
13433
|
}
|
|
12200
13434
|
if (inHeader) {
|
|
12201
|
-
return /* @__PURE__ */ jsx("nav", { "data-gs": "stepper", "aria-label": "Progress", className: cn("
|
|
13435
|
+
return /* @__PURE__ */ jsx("nav", { "data-gs": "stepper", "aria-label": "Progress", className: cn("mx-ds-1", className), children: /* @__PURE__ */ jsx("ol", { role: "list", className: STEP_LIST, children: steps.map((step, i) => {
|
|
12202
13436
|
const status = step.status ?? (i < currentStep ? "complete" : i === currentStep ? "current" : "upcoming");
|
|
12203
13437
|
const isLast = i === steps.length - 1;
|
|
12204
|
-
return /* @__PURE__ */ jsxs("
|
|
13438
|
+
return /* @__PURE__ */ jsxs("li", { className: cn("flex flex-col items-start min-w-0", isLast ? "flex-none" : "flex-1"), children: [
|
|
12205
13439
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center w-full", children: [
|
|
12206
|
-
/* @__PURE__ */ jsx(StepCircle, { status, index: i, label: step.label,
|
|
13440
|
+
/* @__PURE__ */ jsx(StepCircle, { status, index: i, label: step.label, kind: kindOf2(step), onClick: () => onStepChange?.(i) }),
|
|
12207
13441
|
!isLast && /* @__PURE__ */ jsx(
|
|
12208
13442
|
"div",
|
|
12209
13443
|
{
|
|
@@ -12220,7 +13454,7 @@ function Stepper({ steps, currentStep, onStepChange, orientation = "horizontal",
|
|
|
12220
13454
|
{
|
|
12221
13455
|
className: cn(
|
|
12222
13456
|
"text-xs font-medium",
|
|
12223
|
-
status === "current" ? "text-[var(--ds-accent-primary)]" : "text-[var(--ds-text-primary)]"
|
|
13457
|
+
status === "current" ? "text-[var(--ds-accent-primary)]" : kindOf2(step) === "locked" ? "text-[var(--ds-text-muted)]" : "text-[var(--ds-text-primary)]"
|
|
12224
13458
|
),
|
|
12225
13459
|
children: step.label
|
|
12226
13460
|
}
|
|
@@ -12228,15 +13462,15 @@ function Stepper({ steps, currentStep, onStepChange, orientation = "horizontal",
|
|
|
12228
13462
|
step.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-[var(--ds-text-muted)] mt-ds-0.5", children: step.description })
|
|
12229
13463
|
] })
|
|
12230
13464
|
] }, i);
|
|
12231
|
-
}) });
|
|
13465
|
+
}) }) });
|
|
12232
13466
|
}
|
|
12233
13467
|
if (!isHorizontal) {
|
|
12234
|
-
return /* @__PURE__ */ jsx("nav", { "data-gs": "stepper", "aria-label": "Progress", className: cn("flex
|
|
13468
|
+
return /* @__PURE__ */ jsx("nav", { "data-gs": "stepper", "aria-label": "Progress", className, children: /* @__PURE__ */ jsx("ol", { role: "list", className: cn(STEP_LIST, "flex-col items-stretch"), children: steps.map((step, i) => {
|
|
12235
13469
|
const status = step.status ?? (i < currentStep ? "complete" : i === currentStep ? "current" : "upcoming");
|
|
12236
13470
|
const isLast = i === steps.length - 1;
|
|
12237
|
-
return /* @__PURE__ */ jsxs("
|
|
13471
|
+
return /* @__PURE__ */ jsxs("li", { className: "flex gap-ds-3", children: [
|
|
12238
13472
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center", children: [
|
|
12239
|
-
/* @__PURE__ */ jsx(StepCircle, { status, index: i, label: step.label,
|
|
13473
|
+
/* @__PURE__ */ jsx(StepCircle, { status, index: i, label: step.label, kind: kindOf2(step), onClick: () => onStepChange?.(i) }),
|
|
12240
13474
|
!isLast && /* @__PURE__ */ jsx(
|
|
12241
13475
|
"div",
|
|
12242
13476
|
{
|
|
@@ -12253,7 +13487,7 @@ function Stepper({ steps, currentStep, onStepChange, orientation = "horizontal",
|
|
|
12253
13487
|
{
|
|
12254
13488
|
className: cn(
|
|
12255
13489
|
"text-xs font-medium leading-8",
|
|
12256
|
-
status === "current" ? "text-[var(--ds-accent-primary)]" : "text-[var(--ds-text-primary)]"
|
|
13490
|
+
status === "current" ? "text-[var(--ds-accent-primary)]" : kindOf2(step) === "locked" ? "text-[var(--ds-text-muted)]" : "text-[var(--ds-text-primary)]"
|
|
12257
13491
|
),
|
|
12258
13492
|
children: step.label
|
|
12259
13493
|
}
|
|
@@ -12261,18 +13495,18 @@ function Stepper({ steps, currentStep, onStepChange, orientation = "horizontal",
|
|
|
12261
13495
|
step.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-[var(--ds-text-muted)] -mt-1", children: step.description })
|
|
12262
13496
|
] })
|
|
12263
13497
|
] }, i);
|
|
12264
|
-
}) });
|
|
13498
|
+
}) }) });
|
|
12265
13499
|
}
|
|
12266
13500
|
return /* @__PURE__ */ jsx(
|
|
12267
13501
|
"nav",
|
|
12268
13502
|
{
|
|
12269
13503
|
"data-gs": "stepper",
|
|
12270
13504
|
"aria-label": "Progress",
|
|
12271
|
-
className
|
|
12272
|
-
children: steps.map((step, i) => {
|
|
13505
|
+
className,
|
|
13506
|
+
children: /* @__PURE__ */ jsx("ol", { role: "list", className: STEP_LIST, children: steps.map((step, i) => {
|
|
12273
13507
|
const status = step.status ?? (i < currentStep ? "complete" : i === currentStep ? "current" : "upcoming");
|
|
12274
13508
|
const isLast = i === steps.length - 1;
|
|
12275
|
-
return /* @__PURE__ */ jsxs("
|
|
13509
|
+
return /* @__PURE__ */ jsxs("li", { className: "flex flex-1 flex-col items-center", children: [
|
|
12276
13510
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center w-full", children: [
|
|
12277
13511
|
/* @__PURE__ */ jsx(
|
|
12278
13512
|
"div",
|
|
@@ -12283,7 +13517,7 @@ function Stepper({ steps, currentStep, onStepChange, orientation = "horizontal",
|
|
|
12283
13517
|
)
|
|
12284
13518
|
}
|
|
12285
13519
|
),
|
|
12286
|
-
/* @__PURE__ */ jsx(StepCircle, { status, index: i, label: step.label,
|
|
13520
|
+
/* @__PURE__ */ jsx(StepCircle, { status, index: i, label: step.label, kind: kindOf2(step), onClick: () => onStepChange?.(i) }),
|
|
12287
13521
|
/* @__PURE__ */ jsx(
|
|
12288
13522
|
"div",
|
|
12289
13523
|
{
|
|
@@ -12300,7 +13534,7 @@ function Stepper({ steps, currentStep, onStepChange, orientation = "horizontal",
|
|
|
12300
13534
|
{
|
|
12301
13535
|
className: cn(
|
|
12302
13536
|
"text-xs font-medium",
|
|
12303
|
-
status === "current" ? "text-[var(--ds-accent-primary)]" : "text-[var(--ds-text-primary)]"
|
|
13537
|
+
status === "current" ? "text-[var(--ds-accent-primary)]" : kindOf2(step) === "locked" ? "text-[var(--ds-text-muted)]" : "text-[var(--ds-text-primary)]"
|
|
12304
13538
|
),
|
|
12305
13539
|
children: step.label
|
|
12306
13540
|
}
|
|
@@ -12308,33 +13542,41 @@ function Stepper({ steps, currentStep, onStepChange, orientation = "horizontal",
|
|
|
12308
13542
|
step.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-[var(--ds-text-muted)] mt-ds-0.5", children: step.description })
|
|
12309
13543
|
] })
|
|
12310
13544
|
] }, i);
|
|
12311
|
-
})
|
|
13545
|
+
}) })
|
|
12312
13546
|
}
|
|
12313
13547
|
);
|
|
12314
13548
|
}
|
|
12315
|
-
|
|
13549
|
+
var STEP_LIST = "flex items-start list-none m-0 p-0";
|
|
13550
|
+
function StepCircle({ status, index, label, kind, onClick }) {
|
|
13551
|
+
const name = `Step ${index + 1}: ${label}${status === "complete" ? ", completed" : ""}`;
|
|
13552
|
+
const look = cn(
|
|
13553
|
+
"flex items-center justify-center shrink-0 w-8 h-8 rounded-[var(--ds-radius-full)] text-xs font-bold transition-colors",
|
|
13554
|
+
status === "complete" && "bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] text-[var(--ds-text-on-primary)]",
|
|
13555
|
+
status === "current" && `border-2 ${ACTIVE_RING} text-[var(--ds-accent-primary)] bg-[var(--ds-bg-surface)]`,
|
|
13556
|
+
status === "error" && "bg-[var(--ds-status-error)] text-[var(--ds-text-on-error)]",
|
|
13557
|
+
status === "loading" && `border-2 ${ACTIVE_RING} text-[var(--ds-accent-primary)] bg-[var(--ds-bg-surface)] animate-pulse`,
|
|
13558
|
+
status === "upcoming" && "border-[length:var(--ds-border-width)] border-[var(--ds-border-default)] text-[var(--ds-text-muted)] bg-[var(--ds-bg-surface)]"
|
|
13559
|
+
);
|
|
13560
|
+
const glyph = status === "complete" ? /* @__PURE__ */ jsx(Icon, { name: "check", size: 14 }) : status === "error" ? /* @__PURE__ */ jsx(Icon, { name: "warning", size: 14 }) : index + 1;
|
|
13561
|
+
if (kind === "progress") {
|
|
13562
|
+
return /* @__PURE__ */ jsx("span", { role: "img", "aria-label": name, "aria-current": status === "current" ? "step" : void 0, className: look, children: glyph });
|
|
13563
|
+
}
|
|
12316
13564
|
return /* @__PURE__ */ jsx(
|
|
12317
13565
|
"button",
|
|
12318
13566
|
{
|
|
12319
13567
|
type: "button",
|
|
12320
|
-
onClick,
|
|
12321
|
-
disabled:
|
|
12322
|
-
"aria-label":
|
|
13568
|
+
onClick: kind === "open" ? onClick : void 0,
|
|
13569
|
+
disabled: kind === "locked",
|
|
13570
|
+
"aria-label": kind === "locked" ? `${name}, cannot start yet` : name,
|
|
12323
13571
|
"aria-current": status === "current" ? "step" : void 0,
|
|
12324
13572
|
className: cn(
|
|
12325
|
-
|
|
13573
|
+
look,
|
|
12326
13574
|
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
12327
|
-
|
|
12328
|
-
!clickable && "cursor-default",
|
|
12329
|
-
status === "complete" && "bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] text-[var(--ds-text-on-primary)]",
|
|
12330
|
-
status === "current" && `border-2 ${ACTIVE_RING} text-[var(--ds-accent-primary)] bg-[var(--ds-bg-surface)]`,
|
|
12331
|
-
status === "error" && "bg-[var(--ds-status-error)] text-[var(--ds-text-on-error)]",
|
|
12332
|
-
status === "loading" && `border-2 ${ACTIVE_RING} text-[var(--ds-accent-primary)] bg-[var(--ds-bg-surface)] animate-pulse`,
|
|
12333
|
-
status === "upcoming" && "border-[length:var(--ds-border-width)] border-[var(--ds-border-default)] text-[var(--ds-text-muted)] bg-[var(--ds-bg-surface)]",
|
|
13575
|
+
kind === "open" ? "cursor-pointer" : "cursor-not-allowed opacity-disabled",
|
|
12334
13576
|
// a step reached but not done (the user went back) can be gone to: it answers the pointer as the done ones do
|
|
12335
|
-
status === "upcoming" &&
|
|
13577
|
+
status === "upcoming" && kind === "open" && "hover:border-[var(--ds-accent-primary)] hover:text-[var(--ds-accent-primary)]"
|
|
12336
13578
|
),
|
|
12337
|
-
children:
|
|
13579
|
+
children: glyph
|
|
12338
13580
|
}
|
|
12339
13581
|
);
|
|
12340
13582
|
}
|
|
@@ -12546,6 +13788,7 @@ var Sidebar = forwardRef(function Sidebar2({
|
|
|
12546
13788
|
effectiveDarkMode = false;
|
|
12547
13789
|
}
|
|
12548
13790
|
const isDark = effectiveDarkMode ?? variant === "dark";
|
|
13791
|
+
const hydrated = useHydrated();
|
|
12549
13792
|
const showCollapse = type === "traditional" && !mini && !fill2;
|
|
12550
13793
|
const isMinimal = type === "minimal";
|
|
12551
13794
|
const isCompact = type === "compact";
|
|
@@ -12620,7 +13863,7 @@ var Sidebar = forwardRef(function Sidebar2({
|
|
|
12620
13863
|
children: footer
|
|
12621
13864
|
}
|
|
12622
13865
|
),
|
|
12623
|
-
isDark && (() => {
|
|
13866
|
+
isDark && hydrated && (() => {
|
|
12624
13867
|
const root = document.documentElement;
|
|
12625
13868
|
const pageIsDark = root.getAttribute("data-mode") === "dark";
|
|
12626
13869
|
const shadow = root.getAttribute("data-shadow") || "flat";
|
|
@@ -13406,7 +14649,7 @@ function fill(entries, slots) {
|
|
|
13406
14649
|
}
|
|
13407
14650
|
function ToastProvider({ children, maxVisible = 3, position = "bottom-right", duration = 5e3, mode, pauseOnHover = true, coalesce = true }) {
|
|
13408
14651
|
const slots = Math.max(1, Math.floor(Number.isFinite(maxVisible) ? maxVisible : 1));
|
|
13409
|
-
const [
|
|
14652
|
+
const [list2, setList] = useState([]);
|
|
13410
14653
|
const entries = useRef([]);
|
|
13411
14654
|
const isMobile = useBreakpoint("sm");
|
|
13412
14655
|
const shownDuringRuns = useRef([]);
|
|
@@ -13435,7 +14678,7 @@ function ToastProvider({ children, maxVisible = 3, position = "bottom-right", du
|
|
|
13435
14678
|
setBottomNavs((n) => n - 1);
|
|
13436
14679
|
};
|
|
13437
14680
|
}, []);
|
|
13438
|
-
const
|
|
14681
|
+
const commit2 = useCallback((next) => {
|
|
13439
14682
|
entries.current = fill(next, slots);
|
|
13440
14683
|
setList(entries.current);
|
|
13441
14684
|
}, [slots]);
|
|
@@ -13444,9 +14687,9 @@ function ToastProvider({ children, maxVisible = 3, position = "bottom-right", du
|
|
|
13444
14687
|
const reslotted = entries.current.map((e) => e.shown && ++kept > slots ? { ...e, shown: false } : e);
|
|
13445
14688
|
const next = fill(reslotted, slots);
|
|
13446
14689
|
if (next.length === entries.current.length && next.every((e, i) => e === entries.current[i])) return;
|
|
13447
|
-
|
|
13448
|
-
}, [slots,
|
|
13449
|
-
if (
|
|
14690
|
+
commit2(next);
|
|
14691
|
+
}, [slots, commit2]);
|
|
14692
|
+
if (list2.every((t) => !t.shown) && (hovered || focusInside)) {
|
|
13450
14693
|
setHovered(false);
|
|
13451
14694
|
setFocusInside(false);
|
|
13452
14695
|
}
|
|
@@ -13463,11 +14706,11 @@ function ToastProvider({ children, maxVisible = 3, position = "bottom-right", du
|
|
|
13463
14706
|
}).filter((h) => h.text);
|
|
13464
14707
|
pendingHeard.current.clear();
|
|
13465
14708
|
if (!batch.length) return;
|
|
13466
|
-
setHeard((
|
|
14709
|
+
setHeard((list3) => [...list3, ...batch].slice(-5));
|
|
13467
14710
|
const ids = new Set(batch.map((h) => h.id));
|
|
13468
14711
|
const timer = setTimeout(() => {
|
|
13469
14712
|
clearTimers.current.delete(timer);
|
|
13470
|
-
setHeard((
|
|
14713
|
+
setHeard((list3) => list3.filter((h) => !ids.has(h.id)));
|
|
13471
14714
|
}, HEARD_MS);
|
|
13472
14715
|
clearTimers.current.add(timer);
|
|
13473
14716
|
}, 0);
|
|
@@ -13487,60 +14730,60 @@ function ToastProvider({ children, maxVisible = 3, position = "bottom-right", du
|
|
|
13487
14730
|
}, []);
|
|
13488
14731
|
const remove = useCallback((id) => {
|
|
13489
14732
|
leaving(id);
|
|
13490
|
-
|
|
13491
|
-
}, [
|
|
14733
|
+
commit2(entries.current.filter((t) => t.id !== id));
|
|
14734
|
+
}, [commit2, leaving]);
|
|
13492
14735
|
const dismissAll = useCallback(() => {
|
|
13493
14736
|
leaving();
|
|
13494
|
-
|
|
13495
|
-
}, [
|
|
14737
|
+
commit2([]);
|
|
14738
|
+
}, [commit2, leaving]);
|
|
13496
14739
|
const noteShown = useCallback((id, variant, action, fresh) => {
|
|
13497
14740
|
if (runs.current.size) shownDuringRuns.current.push({ seq: ++showSeq.current, at: Date.now(), id, variant, action, fresh });
|
|
13498
14741
|
}, []);
|
|
13499
14742
|
const update2 = useCallback((id, message, options = {}) => {
|
|
13500
|
-
const
|
|
13501
|
-
const at =
|
|
14743
|
+
const list3 = entries.current;
|
|
14744
|
+
const at = list3.findIndex((t2) => t2.id === id);
|
|
13502
14745
|
if (at === -1) return;
|
|
13503
14746
|
pressed.current.delete(id);
|
|
13504
|
-
const t =
|
|
13505
|
-
const next = [...
|
|
14747
|
+
const t = list3[at];
|
|
14748
|
+
const next = [...list3];
|
|
13506
14749
|
next[at] = { ...t, message, variant: options.variant ?? t.variant, duration: options.duration ?? t.duration, action: options.action ?? t.action, actionWindow: options.actionWindow ?? t.actionWindow, key: options.key ?? t.key, version: t.version + 1 };
|
|
13507
|
-
|
|
14750
|
+
commit2(next);
|
|
13508
14751
|
announce(next[at]);
|
|
13509
14752
|
noteShown(id, next[at].variant, !!next[at].action, false);
|
|
13510
|
-
}, [
|
|
14753
|
+
}, [commit2, announce, noteShown]);
|
|
13511
14754
|
const toast = useCallback((message, options = {}) => {
|
|
13512
|
-
const
|
|
14755
|
+
const list3 = entries.current;
|
|
13513
14756
|
const base = { message, variant: options.variant ?? "default", duration: options.duration ?? duration, action: options.action, actionWindow: options.actionWindow, key: options.key };
|
|
13514
14757
|
if (options.id) {
|
|
13515
|
-
const at =
|
|
14758
|
+
const at = list3.findIndex((t) => t.id === options.id);
|
|
13516
14759
|
if (at !== -1) {
|
|
13517
|
-
const next = [...
|
|
13518
|
-
next[at] = { ...
|
|
14760
|
+
const next = [...list3];
|
|
14761
|
+
next[at] = { ...list3[at], ...base, version: list3[at].version + 1 };
|
|
13519
14762
|
pressed.current.delete(options.id);
|
|
13520
|
-
|
|
14763
|
+
commit2(next);
|
|
13521
14764
|
announce(next[at]);
|
|
13522
14765
|
noteShown(options.id, base.variant, !!base.action, false);
|
|
13523
14766
|
return options.id;
|
|
13524
14767
|
}
|
|
13525
14768
|
}
|
|
13526
14769
|
if (coalesce && base.key && mergeable(base)) {
|
|
13527
|
-
const at =
|
|
14770
|
+
const at = list3.findIndex((t) => t.key === base.key && mergeable(t));
|
|
13528
14771
|
if (at !== -1) {
|
|
13529
|
-
const next = [...
|
|
13530
|
-
next[at] = { ...
|
|
13531
|
-
|
|
14772
|
+
const next = [...list3];
|
|
14773
|
+
next[at] = { ...list3[at], ...base, version: list3[at].version + 1 };
|
|
14774
|
+
commit2(next);
|
|
13532
14775
|
announce(next[at]);
|
|
13533
|
-
noteShown(
|
|
13534
|
-
return
|
|
14776
|
+
noteShown(list3[at].id, base.variant, !!base.action, false);
|
|
14777
|
+
return list3[at].id;
|
|
13535
14778
|
}
|
|
13536
14779
|
}
|
|
13537
14780
|
const id = options.id ?? `toast-${++toastSeq}`;
|
|
13538
14781
|
const entry = { id, ...base, shown: false, version: 0 };
|
|
13539
|
-
|
|
14782
|
+
commit2([...list3, entry]);
|
|
13540
14783
|
announce(entry);
|
|
13541
14784
|
noteShown(id, base.variant, !!base.action, true);
|
|
13542
14785
|
return id;
|
|
13543
|
-
}, [duration, coalesce,
|
|
14786
|
+
}, [duration, coalesce, commit2, announce, noteShown]);
|
|
13544
14787
|
const api = useMemo(() => ({
|
|
13545
14788
|
toast,
|
|
13546
14789
|
success: (m, o) => toast(m, { ...o, variant: "success" }),
|
|
@@ -13592,7 +14835,7 @@ function ToastProvider({ children, maxVisible = 3, position = "bottom-right", du
|
|
|
13592
14835
|
if (!entry?.action) return;
|
|
13593
14836
|
const run = entry.action.onClick;
|
|
13594
14837
|
leaving(id);
|
|
13595
|
-
|
|
14838
|
+
commit2(entries.current.map((t) => t.id === id ? { ...t, action: void 0, actionWindow: void 0, version: t.version + 1 } : t));
|
|
13596
14839
|
pressed.current.add(id);
|
|
13597
14840
|
const done = () => {
|
|
13598
14841
|
if (pressed.current.delete(id)) remove(id);
|
|
@@ -13610,15 +14853,15 @@ function ToastProvider({ children, maxVisible = 3, position = "bottom-right", du
|
|
|
13610
14853
|
}
|
|
13611
14854
|
if (isThenable2(result)) result.then(done, failed);
|
|
13612
14855
|
else done();
|
|
13613
|
-
}, [
|
|
14856
|
+
}, [commit2, leaving, remove]);
|
|
13614
14857
|
const lapse = useCallback((id) => {
|
|
13615
|
-
const
|
|
13616
|
-
const at =
|
|
14858
|
+
const list3 = entries.current;
|
|
14859
|
+
const at = list3.findIndex((t) => t.id === id);
|
|
13617
14860
|
if (at === -1) return;
|
|
13618
|
-
const next = [...
|
|
13619
|
-
next[at] = { ...
|
|
13620
|
-
|
|
13621
|
-
}, [
|
|
14861
|
+
const next = [...list3];
|
|
14862
|
+
next[at] = { ...list3[at], action: void 0, actionWindow: void 0, version: list3[at].version + 1 };
|
|
14863
|
+
commit2(next);
|
|
14864
|
+
}, [commit2]);
|
|
13622
14865
|
useEffect(() => {
|
|
13623
14866
|
const onKey = (e) => {
|
|
13624
14867
|
if (e.key !== "F8" || e.defaultPrevented) return;
|
|
@@ -13654,9 +14897,9 @@ function ToastProvider({ children, maxVisible = 3, position = "bottom-right", du
|
|
|
13654
14897
|
}
|
|
13655
14898
|
main.focus();
|
|
13656
14899
|
}
|
|
13657
|
-
}, [
|
|
13658
|
-
const shown =
|
|
13659
|
-
const waiting =
|
|
14900
|
+
}, [list2]);
|
|
14901
|
+
const shown = list2.filter((t) => t.shown);
|
|
14902
|
+
const waiting = list2.length - shown.length;
|
|
13660
14903
|
const isTop = position.startsWith("top");
|
|
13661
14904
|
const hasBottomNav = isMobile && bottomNavs > 0;
|
|
13662
14905
|
return /* @__PURE__ */ jsx(ToastContext.Provider, { value: api, children: /* @__PURE__ */ jsxs(ToastLedgerCtx.Provider, { value: ledger, children: [
|
|
@@ -13937,8 +15180,8 @@ function usePageActionsSlot() {
|
|
|
13937
15180
|
const [asking, setAsking] = useState(0);
|
|
13938
15181
|
const [slots, setSlots] = useState([]);
|
|
13939
15182
|
const register = useCallback((el, size) => {
|
|
13940
|
-
setSlots((
|
|
13941
|
-
return () => setSlots((
|
|
15183
|
+
setSlots((list2) => [...list2.filter((s) => s.el !== el), { el, size }]);
|
|
15184
|
+
return () => setSlots((list2) => list2.filter((s) => s.el !== el));
|
|
13942
15185
|
}, []);
|
|
13943
15186
|
const outerAdd = outer?.add;
|
|
13944
15187
|
const add = useCallback(() => {
|
|
@@ -13961,7 +15204,7 @@ function usePageContainer() {
|
|
|
13961
15204
|
}
|
|
13962
15205
|
function isPageHeaderElement(node) {
|
|
13963
15206
|
if (!isValidElement(node)) return false;
|
|
13964
|
-
const type = node.type;
|
|
15207
|
+
const type = elementType(node.type);
|
|
13965
15208
|
return !!type && typeof type !== "string" && type[PAGE_HEADER_MARK] === true;
|
|
13966
15209
|
}
|
|
13967
15210
|
var OVERLAP_MIN = 24;
|
|
@@ -14106,7 +15349,7 @@ var PageContainer = forwardRef(function PageContainer2({
|
|
|
14106
15349
|
const placement = block ? "block" : r.outside ? "outside" : "inside";
|
|
14107
15350
|
const breadcrumbsInsideHeader = snapping && floatingHeader && contained;
|
|
14108
15351
|
const strip = contained && !breadcrumbsInsideHeader && crumbs ? /* @__PURE__ */ jsx(Breadcrumbs, { variant: "contained", itemVariant: r.breadcrumbStyle, bleed: true, contentMaxWidth: maxWidthValue, separator: r.breadcrumbSeparator, items: headerEl.props.title ? [...crumbs, { label: headerEl.props.title }] : crumbs }) : null;
|
|
14109
|
-
const columnClass = (
|
|
15352
|
+
const columnClass = (pad4) => cn("w-full", paddingClasses[pad4], centered && "mx-auto");
|
|
14110
15353
|
const columnStyle = { maxWidth: maxWidthValue, containerType: "inline-size" };
|
|
14111
15354
|
const header = /* @__PURE__ */ jsx(PageContainerContext, { value: { contentMaxWidth: maxWidthValue, placement, containedBreadcrumbs: contained, breadcrumbsInsideHeader, noBottomMargin: block, overlap: overlapActive, setPinnedHeight, reportHeader, requestContentWidth }, children: renderHeader ? renderHeader(headerEl) : headerEl });
|
|
14112
15355
|
const contentPadding = floatingHeader && shell?.isMobile ? "none" : padding;
|
|
@@ -14156,7 +15399,7 @@ function outerHeight(el) {
|
|
|
14156
15399
|
return el.getBoundingClientRect().height + (parseFloat(s.marginTop) || 0) + (parseFloat(s.marginBottom) || 0);
|
|
14157
15400
|
}
|
|
14158
15401
|
function Breadcrumbs2({ items, onLight, onTint, pill, separator = "chevron" }) {
|
|
14159
|
-
const
|
|
15402
|
+
const follow2 = useCrumbFollow();
|
|
14160
15403
|
if (!items.length) return null;
|
|
14161
15404
|
const mutedCls = onLight ? "text-[var(--ds-text-on-primary)]/40" : onTint ? "text-[var(--ds-text-muted-on-tint)]" : "text-[var(--ds-text-secondary)]";
|
|
14162
15405
|
const sepEl = (key) => {
|
|
@@ -14179,7 +15422,7 @@ function Breadcrumbs2({ items, onLight, onTint, pill, separator = "chevron" }) {
|
|
|
14179
15422
|
"a",
|
|
14180
15423
|
{
|
|
14181
15424
|
href: item.href ?? "#",
|
|
14182
|
-
onClick: (e) =>
|
|
15425
|
+
onClick: (e) => follow2(e, item),
|
|
14183
15426
|
className: cn(
|
|
14184
15427
|
"transition-colors duration-[var(--ds-transition-speed)]",
|
|
14185
15428
|
onLight ? "text-[var(--ds-text-on-primary)]/60 hover:text-[var(--ds-text-on-primary)]/90" : cn(mutedCls, "hover:text-[var(--ds-text-primary)]"),
|
|
@@ -14343,7 +15586,7 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
14343
15586
|
const contentMaxWidth = contentMaxWidthProp ?? container?.contentMaxWidth;
|
|
14344
15587
|
const insidePaddedColumn = !!container?.insidePaddedColumn;
|
|
14345
15588
|
const gutterWidth = insidePaddedColumn ? void 0 : contentMaxWidth;
|
|
14346
|
-
const floating = isFloating && !insidePaddedColumn;
|
|
15589
|
+
const floating = isFloating && !insidePaddedColumn && container?.placement !== "block";
|
|
14347
15590
|
const stickyTop = shell ? "top-0" : "top-[var(--ds-navbar-height)]";
|
|
14348
15591
|
const snapping = behavior === "snapping";
|
|
14349
15592
|
const inlineBreadcrumbs = container?.containedBreadcrumbs && !snapping ? void 0 : breadcrumbs;
|
|
@@ -14392,7 +15635,7 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
14392
15635
|
}
|
|
14393
15636
|
let header;
|
|
14394
15637
|
if (variant === "minimal") {
|
|
14395
|
-
header = /* @__PURE__ */ jsx(MinimalHeader, { title,
|
|
15638
|
+
header = /* @__PURE__ */ jsx(MinimalHeader, { title, caption, focusBack, badge, breadcrumbs: inlineBreadcrumbs, actions: shownActions, tabs, breadcrumbPill: bcPill, breadcrumbSeparator: bcSep, as: Heading, className, headerRef: floating ? void 0 : ref, isFloating: floating, contentMaxWidth: gutterWidth });
|
|
14396
15639
|
} else if (variant === "tabs-integrated") {
|
|
14397
15640
|
header = /* @__PURE__ */ jsx(
|
|
14398
15641
|
TabsIntegratedHeader,
|
|
@@ -14567,7 +15810,6 @@ function DefaultHeader({
|
|
|
14567
15810
|
}
|
|
14568
15811
|
function MinimalHeader({
|
|
14569
15812
|
title,
|
|
14570
|
-
description,
|
|
14571
15813
|
caption,
|
|
14572
15814
|
focusBack,
|
|
14573
15815
|
badge,
|
|
@@ -14595,7 +15837,6 @@ function MinimalHeader({
|
|
|
14595
15837
|
] }),
|
|
14596
15838
|
actions && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions }) })
|
|
14597
15839
|
] }),
|
|
14598
|
-
description && /* @__PURE__ */ jsx(ClampedText, { className: "mt-ds-1 text-sm text-[var(--ds-text-secondary)]", children: description }),
|
|
14599
15840
|
tabs && /* @__PURE__ */ jsx(TabRow, { hasCaption: !!caption, className: "mt-ds-3 -mx-ds-1", children: tabs })
|
|
14600
15841
|
] }) });
|
|
14601
15842
|
}
|
|
@@ -14887,7 +16128,6 @@ function SnappingHeader({
|
|
|
14887
16128
|
] }),
|
|
14888
16129
|
actions && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions }) })
|
|
14889
16130
|
] }),
|
|
14890
|
-
description && /* @__PURE__ */ jsx(ClampedText, { className: "mt-ds-1 text-sm text-[var(--ds-text-secondary)]", children: description }),
|
|
14891
16131
|
filters && /* @__PURE__ */ jsx(FilterRow, { className: "mt-ds-3", children: filters }),
|
|
14892
16132
|
expandedContent && /* @__PURE__ */ jsx("div", { className: "mt-ds-3", children: expandedContent }),
|
|
14893
16133
|
tabs && /* @__PURE__ */ jsx(TabRow, { hasCaption: !!caption, className: "mt-ds-3 -mx-ds-1", children: tabs })
|
|
@@ -15022,7 +16262,7 @@ function TabsIntegratedHeader({
|
|
|
15022
16262
|
}) {
|
|
15023
16263
|
const hasBreadcrumbs = !!(breadcrumbs && breadcrumbs.length > 0);
|
|
15024
16264
|
const inner = floatingContentProps(isFloating, contentMaxWidth);
|
|
15025
|
-
return /* @__PURE__ */ jsx("header", { "data-gs": "page-header", ref: headerRef, className: cn(hasBreadcrumbs ? "pt-ds-3" : "pt-ds-6", "pb-ds-
|
|
16265
|
+
return /* @__PURE__ */ jsx("header", { "data-gs": "page-header", ref: headerRef, className: cn(hasBreadcrumbs ? "pt-ds-3" : "pt-ds-6", "pb-ds-6", isFloating && cn(FLOATING_HEADER, "overflow-hidden"), className), children: /* @__PURE__ */ jsxs("div", { className: inner.className, style: inner.style, children: [
|
|
15026
16266
|
focusBack && /* @__PURE__ */ jsx(BackLink, { onClick: focusBack }),
|
|
15027
16267
|
hasBreadcrumbs && /* @__PURE__ */ jsx(Breadcrumbs2, { items: breadcrumbs, pill: breadcrumbPill, separator: breadcrumbSeparator }),
|
|
15028
16268
|
/* @__PURE__ */ jsxs("div", { className: cn(
|
|
@@ -15457,194 +16697,6 @@ function NavMenuGroup({
|
|
|
15457
16697
|
)) })
|
|
15458
16698
|
] });
|
|
15459
16699
|
}
|
|
15460
|
-
var DEFAULT_BUTTON_ATTR = "data-dialog-default-button";
|
|
15461
|
-
var sizeClasses = {
|
|
15462
|
-
// round 16 (the owner's item 5): the small dialog is 448 px, not 384 — a delete confirmation with a typed field was cramped
|
|
15463
|
-
sm: "max-w-md",
|
|
15464
|
-
md: "max-w-lg",
|
|
15465
|
-
lg: "max-w-2xl",
|
|
15466
|
-
xl: "max-w-4xl",
|
|
15467
|
-
full: "max-w-[calc(100vw-2rem)]"
|
|
15468
|
-
};
|
|
15469
|
-
function Dialog({ open, onClose: onCloseProp, title, description, children, footer, variant = "default", size = "md", alert = false, container, onSubmit, dirty, onDiscard }) {
|
|
15470
|
-
const { marked, mark } = useOverlayMark(open);
|
|
15471
|
-
const guard = useDirtyGuard(dirty ?? marked, onCloseProp, onDiscard);
|
|
15472
|
-
const onClose = guard.requestClose;
|
|
15473
|
-
const titleId = useId();
|
|
15474
|
-
const descriptionId = useId();
|
|
15475
|
-
const isMobile = useBreakpoint("sm");
|
|
15476
|
-
const overlayRef = useRef(null);
|
|
15477
|
-
const dialogRef = useRef(null);
|
|
15478
|
-
const opener = useRef(null);
|
|
15479
|
-
const defaultButtonRef = useRef(null);
|
|
15480
|
-
const bodyRef = useScrollbarInset();
|
|
15481
|
-
const onCloseRef = useLatest(onClose);
|
|
15482
|
-
const onSubmitRef = useLatest(onSubmit);
|
|
15483
|
-
const isTopLayer = useOverlayLayer(open);
|
|
15484
|
-
useFocusTrap(dialogRef, open, isTopLayer);
|
|
15485
|
-
const before = useFocusBeforeOpen(open);
|
|
15486
|
-
useEffect(() => {
|
|
15487
|
-
if (!open) return;
|
|
15488
|
-
const active = before.current;
|
|
15489
|
-
opener.current = active instanceof HTMLElement && active !== document.body && active.isConnected ? rememberFocus(active) : null;
|
|
15490
|
-
}, [open, before]);
|
|
15491
|
-
useEffect(() => {
|
|
15492
|
-
if (!open) return;
|
|
15493
|
-
requestAnimationFrame(() => {
|
|
15494
|
-
focusInitial(dialogRef.current, { destructive: variant === "destructive" });
|
|
15495
|
-
});
|
|
15496
|
-
}, [open, variant]);
|
|
15497
|
-
useEffect(() => {
|
|
15498
|
-
if (!open) return;
|
|
15499
|
-
const handler = (e) => {
|
|
15500
|
-
if (e.key !== "Escape" || e.defaultPrevented || !isTopLayer()) return;
|
|
15501
|
-
e.preventDefault();
|
|
15502
|
-
onCloseRef.current();
|
|
15503
|
-
};
|
|
15504
|
-
document.addEventListener("keydown", handler);
|
|
15505
|
-
return () => {
|
|
15506
|
-
document.removeEventListener("keydown", handler);
|
|
15507
|
-
};
|
|
15508
|
-
}, [open, onCloseRef, isTopLayer]);
|
|
15509
|
-
useEffect(() => {
|
|
15510
|
-
if (!open) return;
|
|
15511
|
-
lockBodyScroll();
|
|
15512
|
-
return () => {
|
|
15513
|
-
unlockBodyScroll();
|
|
15514
|
-
const r = opener.current;
|
|
15515
|
-
opener.current = null;
|
|
15516
|
-
const active = document.activeElement;
|
|
15517
|
-
if (!active || active === document.body || !active.isConnected) r?.restore();
|
|
15518
|
-
};
|
|
15519
|
-
}, [open]);
|
|
15520
|
-
if (!open) return null;
|
|
15521
|
-
return createPortal(
|
|
15522
|
-
/* @__PURE__ */ jsxs(
|
|
15523
|
-
"div",
|
|
15524
|
-
{
|
|
15525
|
-
ref: overlayRef,
|
|
15526
|
-
className: cn("fixed inset-0 z-[var(--ds-z-modal)] flex items-center justify-center", !isMobile && "p-ds-4"),
|
|
15527
|
-
children: [
|
|
15528
|
-
/* @__PURE__ */ jsx(
|
|
15529
|
-
"div",
|
|
15530
|
-
{
|
|
15531
|
-
className: "fixed inset-0 bg-black/50 [backdrop-filter:blur(calc(var(--ds-glass-blur)*0.3))] [-webkit-backdrop-filter:blur(calc(var(--ds-glass-blur)*0.3))]",
|
|
15532
|
-
onClick: alert ? void 0 : onClose,
|
|
15533
|
-
"aria-hidden": "true"
|
|
15534
|
-
}
|
|
15535
|
-
),
|
|
15536
|
-
/* @__PURE__ */ jsxs(
|
|
15537
|
-
"form",
|
|
15538
|
-
{
|
|
15539
|
-
onSubmit: (e) => {
|
|
15540
|
-
if (e.target !== e.currentTarget) return;
|
|
15541
|
-
e.preventDefault();
|
|
15542
|
-
e.stopPropagation();
|
|
15543
|
-
if (variant === "destructive") return;
|
|
15544
|
-
const submitter = e.nativeEvent.submitter;
|
|
15545
|
-
const implicit = !submitter || submitter === defaultButtonRef.current;
|
|
15546
|
-
if (!implicit && submitter.getAttribute("type") !== "submit") return;
|
|
15547
|
-
if (implicit) {
|
|
15548
|
-
const explicit = e.currentTarget.querySelector(`button[type="submit"]:not([${DEFAULT_BUTTON_ATTR}])`);
|
|
15549
|
-
if (explicit?.disabled) return;
|
|
15550
|
-
}
|
|
15551
|
-
onSubmitRef.current?.();
|
|
15552
|
-
},
|
|
15553
|
-
className: "contents",
|
|
15554
|
-
children: [
|
|
15555
|
-
/* @__PURE__ */ jsx(
|
|
15556
|
-
"button",
|
|
15557
|
-
{
|
|
15558
|
-
ref: defaultButtonRef,
|
|
15559
|
-
type: "submit",
|
|
15560
|
-
tabIndex: -1,
|
|
15561
|
-
"aria-hidden": "true",
|
|
15562
|
-
className: "sr-only",
|
|
15563
|
-
...{ [DEFAULT_BUTTON_ATTR]: "" }
|
|
15564
|
-
}
|
|
15565
|
-
),
|
|
15566
|
-
/* @__PURE__ */ jsxs(
|
|
15567
|
-
"div",
|
|
15568
|
-
{
|
|
15569
|
-
ref: dialogRef,
|
|
15570
|
-
role: alert ? "alertdialog" : "dialog",
|
|
15571
|
-
...{ [OVERLAY_ROOT_ATTR]: "" },
|
|
15572
|
-
"aria-modal": "true",
|
|
15573
|
-
"data-gs": "dialog",
|
|
15574
|
-
"aria-labelledby": titleId,
|
|
15575
|
-
"aria-describedby": description ? descriptionId : void 0,
|
|
15576
|
-
style: { containerType: "inline-size", "--ds-form-max": "none" },
|
|
15577
|
-
className: cn(
|
|
15578
|
-
// a column: the title row, a body that scrolls when it is taller than the room, and the footer (Sprint 25.14,
|
|
15579
|
-
// with A36's full-screen phone dialog: its content ran past the screen with the footer cut off)
|
|
15580
|
-
"relative z-10 w-full flex flex-col max-h-full",
|
|
15581
|
-
isMobile ? "max-w-none h-full" : sizeClasses[size],
|
|
15582
|
-
OVERLAY_SURFACE,
|
|
15583
|
-
"text-[var(--ds-text-primary)]",
|
|
15584
|
-
GLASS_OVERLAY,
|
|
15585
|
-
// full screen on a phone: no edge to draw, so the content sits at the gutter from the screen's edge
|
|
15586
|
-
isMobile ? "rounded-none" : "rounded-[var(--ds-radius-xl)] border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
15587
|
-
"overflow-hidden",
|
|
15588
|
-
"animate-in fade-in-0 zoom-in-95"
|
|
15589
|
-
),
|
|
15590
|
-
children: [
|
|
15591
|
-
/* @__PURE__ */ jsxs("div", { className: cn("shrink-0 flex items-start gap-ds-3 pt-ds-6 px-[var(--ds-page-gutter)]", children ? "pb-ds-4" : "pb-ds-6"), children: [
|
|
15592
|
-
variant === "destructive" && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center shrink-0 w-10 h-10 rounded-[var(--ds-radius-full)] bg-[var(--ds-status-error-bg)]", children: /* @__PURE__ */ jsx(Icon, { name: "warning", size: 20, className: "text-[var(--ds-status-error)]" }) }),
|
|
15593
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
15594
|
-
/* @__PURE__ */ jsx(
|
|
15595
|
-
"h2",
|
|
15596
|
-
{
|
|
15597
|
-
id: titleId,
|
|
15598
|
-
className: "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] leading-none tracking-tight",
|
|
15599
|
-
children: title
|
|
15600
|
-
}
|
|
15601
|
-
),
|
|
15602
|
-
description && /* @__PURE__ */ jsx("p", { id: descriptionId, className: "mt-ds-2 text-sm text-[var(--ds-text-muted)]", children: description })
|
|
15603
|
-
] }),
|
|
15604
|
-
/* @__PURE__ */ jsx(
|
|
15605
|
-
"button",
|
|
15606
|
-
{
|
|
15607
|
-
type: "button",
|
|
15608
|
-
onClick: onClose,
|
|
15609
|
-
...{ [OVERLAY_CLOSE_ATTR]: "" },
|
|
15610
|
-
className: "shrink-0 text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer",
|
|
15611
|
-
"aria-label": "Close",
|
|
15612
|
-
children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 18 })
|
|
15613
|
-
}
|
|
15614
|
-
)
|
|
15615
|
-
] }),
|
|
15616
|
-
children && /* @__PURE__ */ jsx(
|
|
15617
|
-
"div",
|
|
15618
|
-
{
|
|
15619
|
-
ref: bodyRef,
|
|
15620
|
-
className: "min-h-0 flex-[0_1_auto] overflow-y-auto pb-ds-6",
|
|
15621
|
-
style: {
|
|
15622
|
-
paddingLeft: variant === "destructive" ? "calc(var(--ds-page-gutter) + 2.5rem + var(--ds-space-3))" : "var(--ds-page-gutter)",
|
|
15623
|
-
paddingRight: insetLessScrollbar("var(--ds-page-gutter)")
|
|
15624
|
-
},
|
|
15625
|
-
children: /* @__PURE__ */ jsx(SurfaceBoundary, { children: /* @__PURE__ */ jsx(DrawerFooterCtx, { value: null, children: /* @__PURE__ */ jsx(OverlayMarkScope, { mark, children: /* @__PURE__ */ jsx(OverlayCloseCtx, { value: onClose, children }) }) }) })
|
|
15626
|
-
}
|
|
15627
|
-
),
|
|
15628
|
-
isMobile && /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "flex-1 min-h-0" }),
|
|
15629
|
-
/* @__PURE__ */ jsx(DiscardConfirm, { open: guard.confirming, onKeep: guard.keep, onDiscard: guard.discard }),
|
|
15630
|
-
footer && /* @__PURE__ */ jsx("div", { className: cn(
|
|
15631
|
-
"shrink-0 flex justify-end gap-ds-2 py-ds-4 px-[var(--ds-page-gutter)]",
|
|
15632
|
-
"border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
15633
|
-
"bg-[var(--ds-bg-muted)]",
|
|
15634
|
-
!isMobile && "rounded-b-[var(--ds-radius-xl)]"
|
|
15635
|
-
), children: footer })
|
|
15636
|
-
]
|
|
15637
|
-
}
|
|
15638
|
-
)
|
|
15639
|
-
]
|
|
15640
|
-
}
|
|
15641
|
-
)
|
|
15642
|
-
]
|
|
15643
|
-
}
|
|
15644
|
-
),
|
|
15645
|
-
container ?? document.body
|
|
15646
|
-
);
|
|
15647
|
-
}
|
|
15648
16700
|
function HamburgerButton({ onClick, open, className: cls }) {
|
|
15649
16701
|
return /* @__PURE__ */ jsx(
|
|
15650
16702
|
"button",
|
|
@@ -17130,7 +18182,7 @@ function useFlowSteps(options) {
|
|
|
17130
18182
|
const prev = { ...initialAnswers, ...before.answers };
|
|
17131
18183
|
const next2 = { ...prev, ...patch };
|
|
17132
18184
|
const here = Math.max(step, before.current ?? step);
|
|
17133
|
-
const ahead = (
|
|
18185
|
+
const ahead = (list2) => list2.slice(here).map((s) => s.label).join("\0");
|
|
17134
18186
|
const changes = ahead(shownSteps(steps, prev)) !== ahead(shownSteps(steps, next2));
|
|
17135
18187
|
return { ...before, furthest: changes ? Math.min(before.furthest, here) : before.furthest, answers: next2 };
|
|
17136
18188
|
});
|
|
@@ -17139,10 +18191,12 @@ function useFlowSteps(options) {
|
|
|
17139
18191
|
if (key) storeFor(key).focusStep = target;
|
|
17140
18192
|
go(href(target));
|
|
17141
18193
|
}, [key, go, href]);
|
|
18194
|
+
const canGoBack = useShellPreferences().canNavigateBack ?? PREFERENCE_HOUSE_DEFAULTS.canNavigateBack;
|
|
17142
18195
|
const goTo = useCallback((target) => {
|
|
17143
18196
|
if (!Number.isInteger(target) || target < 1 || target > furthest || target === step) return;
|
|
18197
|
+
if (!canGoBack && target < step) return;
|
|
17144
18198
|
moveTo(target);
|
|
17145
|
-
}, [furthest, step, moveTo]);
|
|
18199
|
+
}, [furthest, step, moveTo, canGoBack]);
|
|
17146
18200
|
const next = useCallback((patch) => {
|
|
17147
18201
|
if (!key) return;
|
|
17148
18202
|
if (patch) setAnswers(patch);
|
|
@@ -17151,7 +18205,7 @@ function useFlowSteps(options) {
|
|
|
17151
18205
|
update(key, (v) => ({ ...v, furthest: Math.max(v.furthest, step + 1), current: step + 1 }));
|
|
17152
18206
|
moveTo(step + 1);
|
|
17153
18207
|
}, [key, setAnswers, steps, answers, shown, step, moveTo]);
|
|
17154
|
-
const back = step > 1 ? () => moveTo(step - 1) : void 0;
|
|
18208
|
+
const back = canGoBack && step > 1 ? () => moveTo(step - 1) : void 0;
|
|
17155
18209
|
const saveAndExit = useCallback(() => {
|
|
17156
18210
|
if (key && stored) update(key, (v) => ({ ...v, current: step }));
|
|
17157
18211
|
const left = focusAfterLeaving();
|
|
@@ -17187,7 +18241,8 @@ function useFlowSteps(options) {
|
|
|
17187
18241
|
disabled: i + 1 > furthest || void 0
|
|
17188
18242
|
})),
|
|
17189
18243
|
currentStep: step - 1,
|
|
17190
|
-
|
|
18244
|
+
// with going back off the list only shows progress: nothing in it can be pressed
|
|
18245
|
+
onStepChange: canGoBack ? (index) => goTo(index + 1) : void 0
|
|
17191
18246
|
},
|
|
17192
18247
|
saveAndExit,
|
|
17193
18248
|
finish
|
|
@@ -17559,6 +18614,6 @@ var TextOverflow = forwardRef(function TextOverflow2({
|
|
|
17559
18614
|
return /* @__PURE__ */ jsx(Tooltip, { content: resolvedTooltipContent, children: content });
|
|
17560
18615
|
});
|
|
17561
18616
|
|
|
17562
|
-
export { Accordion, ActionPanel, ActionPanelGroup, AddAnother, Alert, AsidePanel, AvatarGroup, BottomNav, BulkActionBar, Calendar, Card, CardContent, CardDescription, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, ChatMessageList, ChatPanel, Checkbox, CheckboxGroup, CheckboxGroupItem, Collapsible, ColorPicker, Combobox, CommandPalette, ContextMenu, CornerPanel, DEFAULT_DATE_RANGE_PRESETS, DangerZone, DataList, DatePicker, DateRangePicker, DescriptionList, Dialog, Dock, DropdownMenu, EmptyState, EntityCell, FileUpload, FlowSaved, FormWrapper, Gantt, HoverCard, Kbd, Launcher, MentionInput, MobileHeaderMenu, NavItem, NavMenu, Navbar, NotificationCenter, PageActions, PageContainer, PageHeader, PinInput, Progress, RadioGroup, Rating, RelativeTime, ScrollArea, SectionHeading, SegmentedControl, SettingsLayout, Sheet, Sidebar, SidebarNav, SliderRange, StackedList, StatsCard, StatusDot, Stepper, TIME_ZOOMS, Table, TableToolbar, Tabs, Tag, TagInput, TextOverflow, TimeBar, TimePicker, TimeRow, TimeScaleHeader, TimeViewport, Timeline, TimezoneSelect, Toast, ToastProvider, Tour, TransferList, TreeView, browserTimeZone, canonicalTimeZone, dateOfDay, dayOf, endDayOf, fitLabel, fitLabels, formatDateRange,
|
|
18617
|
+
export { Accordion, ActionPanel, ActionPanelGroup, AddAnother, Alert, AsidePanel, AvatarGroup, BottomNav, BulkActionBar, Calendar, Card, CardContent, CardDescription, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, ChatMessageList, ChatPanel, Checkbox, CheckboxGroup, CheckboxGroupItem, Collapsible, CollapsibleContent, CollapsibleTrigger, ColorPicker, Combobox, CommandPalette, ContextMenu, CornerPanel, DEFAULT_DATE_RANGE_PRESETS, DangerZone, DataList, DatePicker, DateRangePicker, DescriptionList, Dialog, Dock, DropdownMenu, EmptyState, EntityCell, FileUpload, FlowSaved, FormWrapper, Gantt, HoverCard, Kbd, Launcher, LocaleProvider, MentionInput, MobileHeaderMenu, NavItem, NavMenu, Navbar, NotificationCenter, PageActions, PageContainer, PageHeader, PinInput, Progress, RadioGroup, Rating, RecurrencePicker, RecurrenceScopeDialog, RelativeTime, ScrollArea, SectionHeading, SegmentedControl, SettingsLayout, Sheet, Sidebar, SidebarNav, SliderRange, StackedList, StatsCard, StatusDot, Stepper, TIME_ZOOMS, Table, TableToolbar, Tabs, TabsContent, TabsList, TabsTrigger, Tag, TagInput, TextOverflow, TimeBar, TimePicker, TimeRow, TimeScaleHeader, TimeViewport, Timeline, TimezoneSelect, Toast, ToastProvider, Tour, TransferList, TreeView, browserTimeZone, canonicalTimeZone, countEdited, dateOfDay, dayOf, deleteOccurrence, describeRecurrence, endDayOf, fitLabel, fitLabels, formatDateRange, nthOf, occurrenceOn, occurrences, parseRRule, readFlowProgress, readRecurrence, recurrencePresets, sameRecurrence, saveOccurrence, timeExtent, timeZoneOffset, toRRule, useBrowserTimeZone, useContentWidth, useDestructiveAction, useFittedLabels, useFlowSteps, useRelativeTimeFormat, useSidebar, useTextMeasure, useTimeScale, useTimeViewport, useTimeViewportLayout, useToast, useToastOptional };
|
|
17563
18618
|
//# sourceMappingURL=index.js.map
|
|
17564
18619
|
//# sourceMappingURL=index.js.map
|