gridsmith-ui 0.29.1 → 0.30.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +94 -0
- package/README.md +5 -1
- package/dist/DropdownMenu-DqT7ZQ0D.d.ts +39 -0
- package/dist/charts.js +24 -9
- package/dist/charts.js.map +1 -1
- package/dist/chat.js +7 -7
- package/dist/{chunk-MFAWJSMJ.js → chunk-6C2IUMY7.js} +4 -23
- package/dist/chunk-6C2IUMY7.js.map +1 -0
- package/dist/{chunk-OYNUU346.js → chunk-7QLXYRPD.js} +3 -12
- package/dist/chunk-7QLXYRPD.js.map +1 -0
- package/dist/{chunk-FD4YED7O.js → chunk-DBHVJ7Z3.js} +5 -49
- package/dist/chunk-DBHVJ7Z3.js.map +1 -0
- package/dist/chunk-IELIF4PJ.js +110 -0
- package/dist/chunk-IELIF4PJ.js.map +1 -0
- package/dist/chunk-ISONVOA7.js +316 -0
- package/dist/chunk-ISONVOA7.js.map +1 -0
- package/dist/{chunk-4TUJXDRU.js → chunk-KMKBOTFR.js} +93 -32
- package/dist/chunk-KMKBOTFR.js.map +1 -0
- package/dist/{chunk-MKFWHWBK.js → chunk-L6HWACK7.js} +7 -7
- package/dist/chunk-L6HWACK7.js.map +1 -0
- package/dist/chunk-LJYSVZMI.js +25 -0
- package/dist/chunk-LJYSVZMI.js.map +1 -0
- package/dist/{chunk-6A5RHW2W.js → chunk-NEUWZUK6.js} +4 -5
- package/dist/chunk-NEUWZUK6.js.map +1 -0
- package/dist/chunk-NKUCS67T.js +13 -0
- package/dist/chunk-NKUCS67T.js.map +1 -0
- package/dist/{chunk-RECCCA7Z.js → chunk-OVHBQT3Z.js} +6 -5
- package/dist/chunk-OVHBQT3Z.js.map +1 -0
- package/dist/{chunk-I3MTQ3CS.js → chunk-OX3NNMWG.js} +6 -6
- package/dist/{chunk-I3MTQ3CS.js.map → chunk-OX3NNMWG.js.map} +1 -1
- package/dist/{chunk-ZI3OQDET.js → chunk-R5QXMNW7.js} +297 -15
- package/dist/chunk-R5QXMNW7.js.map +1 -0
- package/dist/chunk-SJZWEBHL.js +58 -0
- package/dist/chunk-SJZWEBHL.js.map +1 -0
- package/dist/{chunk-FUKSLQ77.js → chunk-SLRTSBCJ.js} +91 -51
- package/dist/chunk-SLRTSBCJ.js.map +1 -0
- package/dist/chunk-T52LAFKG.js +1350 -0
- package/dist/chunk-T52LAFKG.js.map +1 -0
- package/dist/chunk-TYNDXMBV.js +105 -0
- package/dist/chunk-TYNDXMBV.js.map +1 -0
- package/dist/{chunk-37WOC7F7.js → chunk-UDJOIVKQ.js} +31 -113
- package/dist/chunk-UDJOIVKQ.js.map +1 -0
- package/dist/{chunk-RJEUQ7RL.js → chunk-ULCACQSA.js} +47 -90
- package/dist/chunk-ULCACQSA.js.map +1 -0
- package/dist/{chunk-HP7WUZPK.js → chunk-WIUGPZOH.js} +10 -3
- package/dist/chunk-WIUGPZOH.js.map +1 -0
- package/dist/{chunk-JTU7OBYJ.js → chunk-YL5KD5RC.js} +4 -3
- package/dist/chunk-YL5KD5RC.js.map +1 -0
- package/dist/data-grid.d.ts +25 -6
- package/dist/data-grid.js +180 -58
- package/dist/data-grid.js.map +1 -1
- package/dist/editor-mentions.js +4 -5
- package/dist/editor-mentions.js.map +1 -1
- package/dist/editor.js +11 -8
- package/dist/editor.js.map +1 -1
- package/dist/{feather-FNBQ74RR.js → feather-XFFEFLTV.js} +5 -3
- package/dist/feather-XFFEFLTV.js.map +1 -0
- package/dist/{heroicons-DODCSYWD.js → heroicons-L6DOHBEA.js} +5 -3
- package/dist/heroicons-L6DOHBEA.js.map +1 -0
- package/dist/icons.d.ts +1 -1
- package/dist/icons.js +1 -1
- package/dist/index.d.ts +138 -39
- package/dist/index.js +846 -1667
- package/dist/index.js.map +1 -1
- package/dist/kanban.d.ts +26 -8
- package/dist/kanban.js +204 -79
- package/dist/kanban.js.map +1 -1
- package/dist/{lucide-ZWE3EPGP.js → lucide-JOORDTO6.js} +5 -3
- package/dist/lucide-JOORDTO6.js.map +1 -0
- package/dist/{phosphor-DIHPA4AJ.js → phosphor-TKGDYNGR.js} +5 -3
- package/dist/phosphor-TKGDYNGR.js.map +1 -0
- package/dist/resizable.js +47 -16
- package/dist/resizable.js.map +1 -1
- package/dist/roots.css +12 -8
- package/dist/{table-utils-CxnpFHRF.d.ts → table-utils-BXkP-2Hx.d.ts} +3 -1
- package/dist/{tabler-D3VYTSGI.js → tabler-YGETLYRU.js} +5 -3
- package/dist/tabler-YGETLYRU.js.map +1 -0
- package/dist/tokens.css +14 -0
- package/dist/utils.js.map +1 -1
- package/dist/virtualized.d.ts +6 -1
- package/dist/virtualized.js +17 -13
- package/dist/virtualized.js.map +1 -1
- package/dist-static/tokens.css +14 -0
- package/package.json +1 -1
- package/dist/chunk-37WOC7F7.js.map +0 -1
- package/dist/chunk-4TUJXDRU.js.map +0 -1
- package/dist/chunk-6A5RHW2W.js.map +0 -1
- package/dist/chunk-FD4YED7O.js.map +0 -1
- package/dist/chunk-FUKSLQ77.js.map +0 -1
- package/dist/chunk-HP7WUZPK.js.map +0 -1
- package/dist/chunk-JTU7OBYJ.js.map +0 -1
- package/dist/chunk-MFAWJSMJ.js.map +0 -1
- package/dist/chunk-MKFWHWBK.js.map +0 -1
- package/dist/chunk-OYNUU346.js.map +0 -1
- package/dist/chunk-QM4SJKWV.js +0 -51
- package/dist/chunk-QM4SJKWV.js.map +0 -1
- package/dist/chunk-QNHVPE2B.js +0 -117
- package/dist/chunk-QNHVPE2B.js.map +0 -1
- package/dist/chunk-RECCCA7Z.js.map +0 -1
- package/dist/chunk-RJEUQ7RL.js.map +0 -1
- package/dist/chunk-WH2FUFAC.js +0 -15
- package/dist/chunk-WH2FUFAC.js.map +0 -1
- package/dist/chunk-ZI3OQDET.js.map +0 -1
- package/dist/feather-FNBQ74RR.js.map +0 -1
- package/dist/heroicons-DODCSYWD.js.map +0 -1
- package/dist/lucide-ZWE3EPGP.js.map +0 -1
- package/dist/phosphor-DIHPA4AJ.js.map +0 -1
- package/dist/tabler-D3VYTSGI.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,171 +1,59 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useAppShell, REACT_VERSION_PROBLEM, Breadcrumbs, useCrumbFollow, crumbGoes, useCornerInset, NAVBAR_INSET_PRIORITY, useOverlayMark, useDirtyGuard, useScrollbarInset, DrawerFooterCtx, OverlayMarkScope, OverlayCloseCtx, insetLessScrollbar, DiscardConfirm, OVERLAY_ROOT_ATTR, OverlayMarkCtx, useCompact, useElementWidth, DrawerPanel, useCloseSettle, besideRoom, PANEL_INSET_PRIORITY, Drawer, useRememberedWidth, pxOf, ResizeEdge, LAUNCHER_INSET_PRIORITY, defaultMaxWidth } from './chunk-
|
|
3
|
-
export { AppShell, Breadcrumbs, Drawer, SkipLink, useAppShell, useUnsavedChanges } from './chunk-
|
|
4
|
-
import { Skeleton, TITLE_TEXT
|
|
5
|
-
export { Skeleton
|
|
2
|
+
import { useAppShell, REACT_VERSION_PROBLEM, Breadcrumbs, useCrumbFollow, crumbGoes, useCornerInset, NAVBAR_INSET_PRIORITY, useOverlayMark, useDirtyGuard, useScrollbarInset, DrawerFooterCtx, OverlayMarkScope, OverlayCloseCtx, insetLessScrollbar, DiscardConfirm, OVERLAY_ROOT_ATTR, OverlayMarkCtx, useCompact, useElementWidth, DrawerPanel, useCloseSettle, besideRoom, PANEL_INSET_PRIORITY, Drawer, useRememberedWidth, pxOf, ResizeEdge, LAUNCHER_INSET_PRIORITY, defaultMaxWidth } from './chunk-KMKBOTFR.js';
|
|
3
|
+
export { AppShell, Breadcrumbs, Drawer, SkipLink, useAppShell, useUnsavedChanges } from './chunk-KMKBOTFR.js';
|
|
4
|
+
import { Skeleton, TITLE_TEXT } from './chunk-6C2IUMY7.js';
|
|
5
|
+
export { Skeleton } from './chunk-6C2IUMY7.js';
|
|
6
6
|
import { useScrollEdges, EDGE_FADE } from './chunk-3BRQRKDO.js';
|
|
7
|
-
import { Avatar, foldForSearch, useActiveOptionInView, shownMentions, matchMentions, mentionOptionId, MentionList, initialsOf } from './chunk-
|
|
8
|
-
export { Avatar } from './chunk-
|
|
9
|
-
import { Link } from './chunk-
|
|
10
|
-
export { CodeBlock, Divider, Link } from './chunk-
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
export {
|
|
17
|
-
import {
|
|
18
|
-
export {
|
|
19
|
-
import {
|
|
20
|
-
|
|
7
|
+
import { Avatar, foldForSearch, useActiveOptionInView, shownMentions, matchMentions, mentionOptionId, MentionList, initialsOf } from './chunk-NEUWZUK6.js';
|
|
8
|
+
export { Avatar } from './chunk-NEUWZUK6.js';
|
|
9
|
+
import { Link } from './chunk-OX3NNMWG.js';
|
|
10
|
+
export { CodeBlock, Divider, Link } from './chunk-OX3NNMWG.js';
|
|
11
|
+
import { DropdownMenu } from './chunk-ISONVOA7.js';
|
|
12
|
+
export { DropdownMenu } from './chunk-ISONVOA7.js';
|
|
13
|
+
import { useFillHeight, FillContext } from './chunk-DBHVJ7Z3.js';
|
|
14
|
+
import { useKeyboardScroll } from './chunk-SJZWEBHL.js';
|
|
15
|
+
import { Badge } from './chunk-OVHBQT3Z.js';
|
|
16
|
+
export { Badge } from './chunk-OVHBQT3Z.js';
|
|
17
|
+
import { localeCache, startOfDay, addDays, useWeekStart, useDateWords, localeDayFirst, dayKey, moveDay, addMonths, DateSegmentFields, getMonthGrid, isSameMonth, isSameDay, DatePicker, timeSegments, pad2, inferColumnKinds, useCardsSwitch, CARDS_BELOW, kindOfRenderedText, Checkbox, CardValue, SortIndicator, startOfWeek, endOfWeek, addMonthsClamped, isExcludedDay, CutCell, CutEmail, stepValue, separatorMovesOn, TIME_SEPARATORS, typeDigit, getEventsForDay, layoutWeek, isWeekend, getWeekDays, isBarEvent, layoutPieces, dayPieces, groupEventsByDay, timeToFraction } from './chunk-T52LAFKG.js';
|
|
18
|
+
export { Checkbox, CheckboxGroup, CheckboxGroupItem, DatePicker, HoverCard, TextOverflow } from './chunk-T52LAFKG.js';
|
|
19
|
+
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-SLRTSBCJ.js';
|
|
20
|
+
export { Dropdown, Field, InlineFieldError, Input, Label, NumberInput, Pagination, Popover, Textarea, Toggle, usePagination } from './chunk-SLRTSBCJ.js';
|
|
21
|
+
import { useShellPreferences, PREFERENCE_HOUSE_DEFAULTS, formatRelativeTime, thresholdOf, toMillis, formatFullTime, datedMillis, preferenceActionKey, DAY, HOUR, MINUTE } from './chunk-TYNDXMBV.js';
|
|
22
|
+
export { PreferencesContext, formatFullTime, formatRelativeTime, preferenceActionKey, usePreferences } from './chunk-TYNDXMBV.js';
|
|
23
|
+
import { useFormatLocale, useHydrated, useToday, LocaleContext } from './chunk-LJYSVZMI.js';
|
|
24
|
+
export { useFormatLocale, useHydrated } from './chunk-LJYSVZMI.js';
|
|
25
|
+
import { formatLocale, localeChoice } from './chunk-7QLXYRPD.js';
|
|
26
|
+
import { useInputModality, inputModality } from './chunk-7RKC5C7G.js';
|
|
21
27
|
export { INPUT_MODALITY_ATTR, inputModality, installInputModality, useInputModality } from './chunk-7RKC5C7G.js';
|
|
22
|
-
import { useBreakpoint, readBreakpointPx } from './chunk-ZHUVLBCC.js';
|
|
23
|
-
export { BreakpointWidthProvider, useBreakpoint } from './chunk-ZHUVLBCC.js';
|
|
24
28
|
import { FormChangeCtx, useReportedChange, useOptionalFormContext, FormCtx } from './chunk-72SDAX54.js';
|
|
25
29
|
export { useFormContext } from './chunk-72SDAX54.js';
|
|
26
|
-
import { CardSurfaceCtx, useScrollsInside, SplitPaneCtx, RowsCtx, PageActionsCtx, SurfaceBoundary, useFramesItself, TableCardCtx } from './chunk-
|
|
30
|
+
import { Button, CardSurfaceCtx, useScrollsInside, SplitPaneCtx, RowsCtx, PageActionsCtx, ControlSizeContext, triggerType, SurfaceBoundary, Spinner, useFramesItself, TableCardCtx } from './chunk-ULCACQSA.js';
|
|
31
|
+
export { Button, ButtonSizeContext, ControlSizeContext, Spinner } from './chunk-ULCACQSA.js';
|
|
32
|
+
import { elementType } from './chunk-NKUCS67T.js';
|
|
33
|
+
import { useBreakpoint, readBreakpointPx } from './chunk-ZHUVLBCC.js';
|
|
34
|
+
export { BreakpointWidthProvider, useBreakpoint } from './chunk-ZHUVLBCC.js';
|
|
27
35
|
import { useRevealFocus } from './chunk-HTXP5BMM.js';
|
|
28
36
|
export { useRevealFocus } from './chunk-HTXP5BMM.js';
|
|
29
|
-
import { FOCUSABLE,
|
|
30
|
-
export { useGridKeyboard } from './chunk-
|
|
31
|
-
import { useTextOverflow
|
|
32
|
-
export {
|
|
33
|
-
import {
|
|
34
|
-
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
39
|
-
import { createPortal, flushSync } from 'react-dom';
|
|
37
|
+
import { focusAfterSelfRemoval, FOCUSABLE, useFocusKeptInList, FIELD, ZOOM_KEYS, rovingTabStop, useOverlayLayer, useFocusTrap, useFocusBeforeOpen, rememberOpener, focusInitial, OVERLAY_CLOSE_ATTR, usePopupFocus, CONTROL_ANCESTOR, useGridKeyboard, focusAfterRemoval, useNonModalDialog, useReturnFocus } from './chunk-R5QXMNW7.js';
|
|
38
|
+
export { useGridKeyboard } from './chunk-R5QXMNW7.js';
|
|
39
|
+
import { useTextOverflow } from './chunk-IELIF4PJ.js';
|
|
40
|
+
export { useTextOverflow } from './chunk-IELIF4PJ.js';
|
|
41
|
+
import { AutoTooltip } from './chunk-UDJOIVKQ.js';
|
|
42
|
+
export { Tooltip } from './chunk-UDJOIVKQ.js';
|
|
43
|
+
import { Icon, slotIcon, warnOnce } from './chunk-L6HWACK7.js';
|
|
44
|
+
import { mergeRefs } from './chunk-7Q46JXSK.js';
|
|
45
|
+
import { useLatest, usePosition } from './chunk-WIUGPZOH.js';
|
|
46
|
+
import { cn, FOCUS_RING, GLASS_SURFACE, FOCUS_INSET, PEER_FOCUS_RING, GLASS_BACKDROP, FOCUS_ROOM, lockBodyScroll, unlockBodyScroll, OVERLAY_SURFACE, GLASS_OVERLAY, ERROR_HAS_FOCUS_RING, FIELD_HAS_FOCUS_RING, GROUP_FOCUS_RING, ERROR_ACTIVE_RING, ACTIVE_RING, ERROR_FOCUS_WITHIN_RING, FIELD_FOCUS_WITHIN_RING, GLASS_DROPDOWN, ERROR_FOCUS_RING, FIELD_FOCUS_RING, atLeastFocusRoom } from './chunk-YL5KD5RC.js';
|
|
40
47
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
48
|
+
import { forwardRef, useRef, useId, useEffect, useState, createContext, useCallback, useLayoutEffect, useMemo, useContext, isValidElement, memo, useImperativeHandle, useSyncExternalStore, Children, Fragment as Fragment$1, cloneElement, useReducer } from 'react';
|
|
49
|
+
import { createPortal, flushSync } from 'react-dom';
|
|
41
50
|
|
|
42
|
-
function
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const [open, setOpen] = useState(false);
|
|
47
|
-
const [focusedIdx, setFocusedIdx] = useState(-1);
|
|
48
|
-
const triggerRef = useRef(null);
|
|
49
|
-
const menuRef = useRef(null);
|
|
50
|
-
const pos = usePosition(triggerRef, menuRef, open, { side: "bottom", align, offset: 4, flip: true });
|
|
51
|
-
const enabledIndices = items.reduce((acc, item, i) => {
|
|
52
|
-
if (!isDivider(item) && !item.disabled) acc.push(i);
|
|
53
|
-
return acc;
|
|
54
|
-
}, []);
|
|
55
|
-
const [prevOpen, setPrevOpen] = useState(open);
|
|
56
|
-
if (open !== prevOpen) {
|
|
57
|
-
setPrevOpen(open);
|
|
58
|
-
if (!open) setFocusedIdx(-1);
|
|
59
|
-
}
|
|
60
|
-
const { isTop: isTopLayer, returnFocus } = usePopupFocus(open, { trigger: triggerRef, panel: menuRef, close: () => setOpen(false), tabExits: "any" });
|
|
61
|
-
useEffect(() => {
|
|
62
|
-
if (!open) return;
|
|
63
|
-
const onKeyDown = (e) => {
|
|
64
|
-
if (e.key !== "Escape" || e.defaultPrevented || !isTopLayer()) return;
|
|
65
|
-
e.preventDefault();
|
|
66
|
-
returnFocus();
|
|
67
|
-
setOpen(false);
|
|
68
|
-
};
|
|
69
|
-
const onClick = (e) => {
|
|
70
|
-
const target = e.target;
|
|
71
|
-
if (triggerRef.current?.contains(target) || menuRef.current?.contains(target)) return;
|
|
72
|
-
setOpen(false);
|
|
73
|
-
};
|
|
74
|
-
document.addEventListener("keydown", onKeyDown);
|
|
75
|
-
document.addEventListener("mousedown", onClick);
|
|
76
|
-
return () => {
|
|
77
|
-
document.removeEventListener("keydown", onKeyDown);
|
|
78
|
-
document.removeEventListener("mousedown", onClick);
|
|
79
|
-
};
|
|
80
|
-
}, [open, isTopLayer, returnFocus]);
|
|
81
|
-
useEffect(() => {
|
|
82
|
-
if (open && focusedIdx >= 0) {
|
|
83
|
-
menuRef.current?.querySelector(`[data-index="${focusedIdx}"]`)?.focus();
|
|
84
|
-
}
|
|
85
|
-
}, [open, focusedIdx]);
|
|
86
|
-
function handleMenuKeyDown(e) {
|
|
87
|
-
if (e.key === "ArrowDown") {
|
|
88
|
-
e.preventDefault();
|
|
89
|
-
const curPos = enabledIndices.indexOf(focusedIdx);
|
|
90
|
-
setFocusedIdx(enabledIndices[(curPos + 1) % enabledIndices.length]);
|
|
91
|
-
} else if (e.key === "ArrowUp") {
|
|
92
|
-
e.preventDefault();
|
|
93
|
-
const curPos = enabledIndices.indexOf(focusedIdx);
|
|
94
|
-
setFocusedIdx(enabledIndices[(curPos - 1 + enabledIndices.length) % enabledIndices.length]);
|
|
95
|
-
}
|
|
51
|
+
function selectAllFor(bar) {
|
|
52
|
+
for (let box = bar?.parentElement; bar && box && box !== document.body; box = box.parentElement) {
|
|
53
|
+
const all = Array.from(box.querySelectorAll("[data-ds-select-all] input"));
|
|
54
|
+
if (all.length) return all.find((el) => bar.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING) ?? all[all.length - 1];
|
|
96
55
|
}
|
|
97
|
-
return
|
|
98
|
-
/* @__PURE__ */ jsx(
|
|
99
|
-
Slot,
|
|
100
|
-
{
|
|
101
|
-
...triggerType(trigger),
|
|
102
|
-
"aria-haspopup": "menu",
|
|
103
|
-
"aria-expanded": open,
|
|
104
|
-
ref: triggerRef,
|
|
105
|
-
onClick: () => {
|
|
106
|
-
setOpen(!open);
|
|
107
|
-
if (!open && enabledIndices.length) setFocusedIdx(enabledIndices[0]);
|
|
108
|
-
},
|
|
109
|
-
children: trigger
|
|
110
|
-
}
|
|
111
|
-
),
|
|
112
|
-
open && createPortal(
|
|
113
|
-
/* @__PURE__ */ jsx(
|
|
114
|
-
"div",
|
|
115
|
-
{
|
|
116
|
-
ref: menuRef,
|
|
117
|
-
role: "menu",
|
|
118
|
-
"data-gs": "menu",
|
|
119
|
-
onKeyDown: handleMenuKeyDown,
|
|
120
|
-
className: cn(
|
|
121
|
-
// the items' outline has its 4 px of room at any density (Sprint 30, P3)
|
|
122
|
-
"fixed z-[var(--ds-z-popover)] min-w-[180px] p-[max(var(--ds-space-1),4px)]",
|
|
123
|
-
"bg-[var(--ds-bg-surface-elevated)]",
|
|
124
|
-
GLASS_DROPDOWN,
|
|
125
|
-
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
126
|
-
"rounded-[var(--ds-radius-md)] overflow-hidden",
|
|
127
|
-
className
|
|
128
|
-
),
|
|
129
|
-
style: { top: pos.top, left: pos.left },
|
|
130
|
-
onClick: (e) => e.stopPropagation(),
|
|
131
|
-
children: items.map((item, i) => {
|
|
132
|
-
if (isDivider(item)) {
|
|
133
|
-
return /* @__PURE__ */ jsx("div", { role: "separator", className: "my-ds-1 h-px bg-[var(--ds-border-default)]" }, i);
|
|
134
|
-
}
|
|
135
|
-
return /* @__PURE__ */ jsxs(
|
|
136
|
-
"button",
|
|
137
|
-
{
|
|
138
|
-
type: "button",
|
|
139
|
-
"data-index": i,
|
|
140
|
-
role: "menuitem",
|
|
141
|
-
disabled: item.disabled,
|
|
142
|
-
tabIndex: focusedIdx === i ? 0 : -1,
|
|
143
|
-
onClick: () => {
|
|
144
|
-
if (!item.disabled) {
|
|
145
|
-
returnFocus();
|
|
146
|
-
item.onClick();
|
|
147
|
-
setOpen(false);
|
|
148
|
-
}
|
|
149
|
-
},
|
|
150
|
-
className: cn(
|
|
151
|
-
"flex items-center gap-ds-2 w-full text-left px-ds-3 py-ds-2 text-sm cursor-pointer",
|
|
152
|
-
"transition-colors rounded-[var(--ds-radius-sm)]",
|
|
153
|
-
FOCUS_RING,
|
|
154
|
-
item.disabled ? "opacity-disabled cursor-not-allowed" : item.variant === "destructive" ? "text-[var(--ds-status-error-text)] hover:bg-[var(--ds-status-error-bg)] focus-visible:bg-[var(--ds-status-error-bg)]" : "text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-emphasis)] focus-visible:bg-[var(--ds-bg-emphasis)]"
|
|
155
|
-
),
|
|
156
|
-
children: [
|
|
157
|
-
item.icon && /* @__PURE__ */ jsx(Icon, { name: item.icon, size: 16, className: "shrink-0" }),
|
|
158
|
-
/* @__PURE__ */ jsx("span", { children: item.label })
|
|
159
|
-
]
|
|
160
|
-
},
|
|
161
|
-
i
|
|
162
|
-
);
|
|
163
|
-
})
|
|
164
|
-
}
|
|
165
|
-
),
|
|
166
|
-
container ?? document.body
|
|
167
|
-
)
|
|
168
|
-
] });
|
|
56
|
+
return null;
|
|
169
57
|
}
|
|
170
58
|
function BulkActionBar({ selectedCount, actions, onClearSelection, className }) {
|
|
171
59
|
const isMobile = useBreakpoint("sm");
|
|
@@ -217,7 +105,11 @@ function BulkActionBar({ selectedCount, actions, onClearSelection, className })
|
|
|
217
105
|
"button",
|
|
218
106
|
{
|
|
219
107
|
type: "button",
|
|
220
|
-
onClick:
|
|
108
|
+
onClick: (e) => {
|
|
109
|
+
const bar = e.currentTarget.closest('[role="toolbar"]');
|
|
110
|
+
focusAfterSelfRemoval(e.currentTarget, { item: bar, to: selectAllFor(bar) });
|
|
111
|
+
onClearSelection();
|
|
112
|
+
},
|
|
221
113
|
className: cn("ml-auto text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer", FOCUS_RING),
|
|
222
114
|
"aria-label": "Clear selection",
|
|
223
115
|
children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 16 })
|
|
@@ -468,25 +360,6 @@ function Combobox({ value, onChange: onChangeProp, options, placeholder = "Searc
|
|
|
468
360
|
return /* @__PURE__ */ jsx(AutoTooltip, { content: selectedLabel, disabled: !labelTruncated || open, children: triggerContent });
|
|
469
361
|
}
|
|
470
362
|
|
|
471
|
-
// ../../showcase/src/lib/locale-cache.ts
|
|
472
|
-
var caches = /* @__PURE__ */ new Set();
|
|
473
|
-
function localeCache(limit) {
|
|
474
|
-
const map = /* @__PURE__ */ new Map();
|
|
475
|
-
caches.add(map);
|
|
476
|
-
return (key, make) => {
|
|
477
|
-
const hit = map.get(key);
|
|
478
|
-
if (hit !== void 0) {
|
|
479
|
-
map.delete(key);
|
|
480
|
-
map.set(key, hit);
|
|
481
|
-
return hit;
|
|
482
|
-
}
|
|
483
|
-
const made = make();
|
|
484
|
-
map.set(key, made);
|
|
485
|
-
if (map.size > limit) map.delete(map.keys().next().value);
|
|
486
|
-
return made;
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
|
-
|
|
490
363
|
// ../../showcase/src/lib/time-zones.ts
|
|
491
364
|
function canonicalTimeZone(zone) {
|
|
492
365
|
try {
|
|
@@ -566,7 +439,6 @@ function TimezoneSelect({ value, onChange, placeholder = "Search time zones\u202
|
|
|
566
439
|
return /* @__PURE__ */ jsx(Combobox, { value: stored, onChange, options, placeholder, ...rest });
|
|
567
440
|
}
|
|
568
441
|
var LONGEST_WAIT = DAY;
|
|
569
|
-
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"]';
|
|
570
442
|
var noChange = () => () => {
|
|
571
443
|
};
|
|
572
444
|
var inBrowser = () => true;
|
|
@@ -635,109 +507,6 @@ function RelativeTimeAt({ at, hours, className }) {
|
|
|
635
507
|
mounted ? "browser" : "first"
|
|
636
508
|
) });
|
|
637
509
|
}
|
|
638
|
-
var CHECKBOX_SIZES = {
|
|
639
|
-
sm: { box: "h-[16px] w-[16px]", glyph: 10, label: "text-xs" },
|
|
640
|
-
md: { box: "h-[18px] w-[18px]", glyph: 12, label: "text-sm" }
|
|
641
|
-
};
|
|
642
|
-
function Checkbox({ checked, onChange: onChangeProp, label, size = "md", disabled = false, indeterminate = false, className, ref, ...wiring }) {
|
|
643
|
-
const onChange = useReportedChange(onChangeProp, checked);
|
|
644
|
-
const internalRef = useRef(null);
|
|
645
|
-
const dims = CHECKBOX_SIZES[size];
|
|
646
|
-
const control = useFieldControl(wiring);
|
|
647
|
-
const mergedRef = useCallback(
|
|
648
|
-
(node) => {
|
|
649
|
-
internalRef.current = node;
|
|
650
|
-
if (typeof ref === "function") ref(node);
|
|
651
|
-
else if (ref) ref.current = node;
|
|
652
|
-
},
|
|
653
|
-
[ref]
|
|
654
|
-
);
|
|
655
|
-
useEffect(() => {
|
|
656
|
-
if (internalRef.current) internalRef.current.indeterminate = indeterminate;
|
|
657
|
-
}, [indeterminate]);
|
|
658
|
-
const showDash = indeterminate;
|
|
659
|
-
const filled = checked || indeterminate;
|
|
660
|
-
return /* @__PURE__ */ jsxs(
|
|
661
|
-
"label",
|
|
662
|
-
{
|
|
663
|
-
className: cn(
|
|
664
|
-
"flex items-center gap-ds-2.5 cursor-pointer select-none py-ds-1",
|
|
665
|
-
disabled && "opacity-disabled cursor-not-allowed",
|
|
666
|
-
className
|
|
667
|
-
),
|
|
668
|
-
children: [
|
|
669
|
-
/* @__PURE__ */ jsx(
|
|
670
|
-
"input",
|
|
671
|
-
{
|
|
672
|
-
ref: mergedRef,
|
|
673
|
-
type: "checkbox",
|
|
674
|
-
id: control.id,
|
|
675
|
-
"aria-labelledby": wiring["aria-labelledby"],
|
|
676
|
-
"aria-describedby": control.describedBy,
|
|
677
|
-
"aria-invalid": control.invalid || void 0,
|
|
678
|
-
required: control.required || void 0,
|
|
679
|
-
checked,
|
|
680
|
-
disabled,
|
|
681
|
-
onChange: (e) => onChange(e.target.checked),
|
|
682
|
-
className: "peer sr-only"
|
|
683
|
-
}
|
|
684
|
-
),
|
|
685
|
-
/* @__PURE__ */ jsx(
|
|
686
|
-
"span",
|
|
687
|
-
{
|
|
688
|
-
className: cn(
|
|
689
|
-
"flex items-center justify-center",
|
|
690
|
-
dims.box,
|
|
691
|
-
"shrink-0",
|
|
692
|
-
"rounded-[calc(var(--ds-radius-sm)*0.6)]",
|
|
693
|
-
"border-[2px]",
|
|
694
|
-
"transition-all",
|
|
695
|
-
PEER_FOCUS_RING,
|
|
696
|
-
filled ? cn(CHECK_FILL, "border-[var(--ds-check-border)]") : "bg-[var(--ds-input-bg)] border-[var(--ds-input-border)]",
|
|
697
|
-
disabled && "pointer-events-none"
|
|
698
|
-
),
|
|
699
|
-
children: /* @__PURE__ */ jsx(
|
|
700
|
-
"svg",
|
|
701
|
-
{
|
|
702
|
-
width: dims.glyph,
|
|
703
|
-
height: dims.glyph,
|
|
704
|
-
viewBox: "0 0 12 12",
|
|
705
|
-
fill: "none",
|
|
706
|
-
className: cn(
|
|
707
|
-
"text-[var(--ds-check-fg)] transition-opacity",
|
|
708
|
-
filled ? "opacity-100" : "opacity-0"
|
|
709
|
-
),
|
|
710
|
-
children: showDash ? /* @__PURE__ */ jsx("path", { d: "M3 6H9", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" }) : /* @__PURE__ */ jsx("path", { d: "M2.5 6L5 8.5L9.5 3.5", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
711
|
-
}
|
|
712
|
-
)
|
|
713
|
-
}
|
|
714
|
-
),
|
|
715
|
-
label && /* @__PURE__ */ jsx("span", { className: cn(dims.label, "text-[var(--ds-text-primary)]"), children: label })
|
|
716
|
-
]
|
|
717
|
-
}
|
|
718
|
-
);
|
|
719
|
-
}
|
|
720
|
-
var CheckboxGroupContext = createContext(null);
|
|
721
|
-
function CheckboxGroup({ value, onChange, children, className }) {
|
|
722
|
-
return /* @__PURE__ */ jsx(CheckboxGroupContext, { value: { value, onChange }, children: /* @__PURE__ */ jsx("div", { role: "group", className: cn("flex flex-col gap-ds-2", className), children }) });
|
|
723
|
-
}
|
|
724
|
-
function CheckboxGroupItem({ value, label, disabled }) {
|
|
725
|
-
const ctx = useContext(CheckboxGroupContext);
|
|
726
|
-
const resolvedValue = ctx?.value ?? [];
|
|
727
|
-
const resolvedOnChange = ctx?.onChange;
|
|
728
|
-
const checked = resolvedValue.includes(value);
|
|
729
|
-
return /* @__PURE__ */ jsx(
|
|
730
|
-
Checkbox,
|
|
731
|
-
{
|
|
732
|
-
checked,
|
|
733
|
-
disabled,
|
|
734
|
-
label,
|
|
735
|
-
onChange: (c) => {
|
|
736
|
-
resolvedOnChange?.(c ? [...resolvedValue, value] : resolvedValue.filter((v) => v !== value));
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
);
|
|
740
|
-
}
|
|
741
510
|
function RadioGroup({ value, onChange: onChangeProp, options, orientation = "vertical", className, label, ...wiring }) {
|
|
742
511
|
const onChange = useReportedChange(onChangeProp, value);
|
|
743
512
|
const groupRef = useRef(null);
|
|
@@ -774,6 +543,7 @@ function RadioGroup({ value, onChange: onChangeProp, options, orientation = "ver
|
|
|
774
543
|
ref: groupRef,
|
|
775
544
|
role: "radiogroup",
|
|
776
545
|
id: control.id,
|
|
546
|
+
"aria-label": label || control.labelId ? void 0 : control.label,
|
|
777
547
|
"aria-labelledby": label ? groupId : control.labelId,
|
|
778
548
|
"aria-describedby": control.describedBy,
|
|
779
549
|
"aria-invalid": control.invalid || void 0,
|
|
@@ -833,400 +603,6 @@ function RadioGroup({ value, onChange: onChangeProp, options, orientation = "ver
|
|
|
833
603
|
)
|
|
834
604
|
] });
|
|
835
605
|
}
|
|
836
|
-
|
|
837
|
-
// ../../showcase/src/lib/date-grid.ts
|
|
838
|
-
function addDays(d, n) {
|
|
839
|
-
return new Date(d.getFullYear(), d.getMonth(), d.getDate() + n);
|
|
840
|
-
}
|
|
841
|
-
function addMonthsClamped(d, n) {
|
|
842
|
-
const first = new Date(d.getFullYear(), d.getMonth() + n, 1);
|
|
843
|
-
const last2 = new Date(first.getFullYear(), first.getMonth() + 1, 0).getDate();
|
|
844
|
-
return new Date(first.getFullYear(), first.getMonth(), Math.min(d.getDate(), last2));
|
|
845
|
-
}
|
|
846
|
-
function dayKey(d) {
|
|
847
|
-
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
848
|
-
}
|
|
849
|
-
function moveDay(from, key, shift, weekStartsOn = 0) {
|
|
850
|
-
const intoWeek = (from.getDay() - weekStartsOn + 7) % 7;
|
|
851
|
-
switch (key) {
|
|
852
|
-
case "ArrowLeft":
|
|
853
|
-
return addDays(from, -1);
|
|
854
|
-
case "ArrowRight":
|
|
855
|
-
return addDays(from, 1);
|
|
856
|
-
case "ArrowUp":
|
|
857
|
-
return addDays(from, -7);
|
|
858
|
-
case "ArrowDown":
|
|
859
|
-
return addDays(from, 7);
|
|
860
|
-
case "Home":
|
|
861
|
-
return addDays(from, -intoWeek);
|
|
862
|
-
case "End":
|
|
863
|
-
return addDays(from, 6 - intoWeek);
|
|
864
|
-
case "PageUp":
|
|
865
|
-
return addMonthsClamped(from, shift ? -12 : -1);
|
|
866
|
-
case "PageDown":
|
|
867
|
-
return addMonthsClamped(from, shift ? 12 : 1);
|
|
868
|
-
default:
|
|
869
|
-
return null;
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
// ../../showcase/src/lib/segments.ts
|
|
874
|
-
function stepValue(spec, current, delta) {
|
|
875
|
-
if (current === null) return delta > 0 ? spec.min : spec.max;
|
|
876
|
-
const span = spec.max - spec.min + 1;
|
|
877
|
-
return spec.min + ((current - spec.min + delta) % span + span) % span;
|
|
878
|
-
}
|
|
879
|
-
function typeDigit(spec, buffer, digit) {
|
|
880
|
-
if (!/^\d$/.test(digit)) return { buffer, value: buffer ? Number(buffer) : null, advance: false };
|
|
881
|
-
let next = buffer + digit;
|
|
882
|
-
if (next.length > spec.maxDigits || Number(next) > spec.max) next = digit;
|
|
883
|
-
const n = Number(next);
|
|
884
|
-
const value = n >= spec.min && n <= spec.max ? n : null;
|
|
885
|
-
const full = next.length >= spec.maxDigits;
|
|
886
|
-
const noRoom = n > 0 && n * 10 > spec.max;
|
|
887
|
-
return { buffer: next, value, advance: full || noRoom };
|
|
888
|
-
}
|
|
889
|
-
var pad2 = (n) => String(n).padStart(2, "0");
|
|
890
|
-
function timeSegments(use24Hour) {
|
|
891
|
-
return [
|
|
892
|
-
{ key: "hour", label: "Hours", min: use24Hour ? 0 : 1, max: use24Hour ? 23 : 12, maxDigits: 2, placeholder: "--" },
|
|
893
|
-
{ key: "minute", label: "Minutes", min: 0, max: 59, maxDigits: 2, placeholder: "--" }
|
|
894
|
-
];
|
|
895
|
-
}
|
|
896
|
-
function dateSegments(dayFirst, daysInMonth = 31) {
|
|
897
|
-
const day = { key: "day", label: "Day", min: 1, max: daysInMonth, maxDigits: 2, placeholder: "dd" };
|
|
898
|
-
const month = { key: "month", label: "Month", min: 1, max: 12, maxDigits: 2, placeholder: "mm" };
|
|
899
|
-
const year = { key: "year", label: "Year", min: 1, max: 9999, maxDigits: 4, placeholder: "yyyy" };
|
|
900
|
-
return dayFirst ? [day, month, year] : [month, day, year];
|
|
901
|
-
}
|
|
902
|
-
var FIRST_DAY_BY_REGION = Object.fromEntries([
|
|
903
|
-
...["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]),
|
|
904
|
-
...["AF", "BH", "DJ", "DZ", "EG", "IQ", "IR", "JO", "KW", "LY", "OM", "QA", "SD", "SY"].map((r) => [r, 6]),
|
|
905
|
-
["MV", 5]
|
|
906
|
-
]);
|
|
907
|
-
function weekStartOf(tag) {
|
|
908
|
-
if (!tag) return void 0;
|
|
909
|
-
try {
|
|
910
|
-
const locale = new Intl.Locale(tag);
|
|
911
|
-
const info = typeof locale.getWeekInfo === "function" ? locale.getWeekInfo() : locale.weekInfo;
|
|
912
|
-
if (info && typeof info.firstDay === "number" && info.firstDay >= 1 && info.firstDay <= 7) return info.firstDay % 7;
|
|
913
|
-
const region = locale.region ?? locale.maximize().region;
|
|
914
|
-
if (!region) return void 0;
|
|
915
|
-
return FIRST_DAY_BY_REGION[region] ?? 1;
|
|
916
|
-
} catch {
|
|
917
|
-
return void 0;
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
var last = null;
|
|
921
|
-
function firstDayFor(spoken, page) {
|
|
922
|
-
for (const tag of [...spoken, page]) {
|
|
923
|
-
const found = weekStartOf(tag);
|
|
924
|
-
if (found !== void 0) return found;
|
|
925
|
-
}
|
|
926
|
-
return 1;
|
|
927
|
-
}
|
|
928
|
-
function regionWeekStart() {
|
|
929
|
-
if (typeof document === "undefined") return 1;
|
|
930
|
-
const spoken = typeof navigator === "undefined" ? [] : navigator.languages?.length ? navigator.languages : navigator.language ? [navigator.language] : [];
|
|
931
|
-
const page = formatLocale();
|
|
932
|
-
const key = `${spoken.join(",")}|${page ?? ""}`;
|
|
933
|
-
if (last?.key === key) return last.day;
|
|
934
|
-
const day = firstDayFor(spoken, page);
|
|
935
|
-
last = { key, day };
|
|
936
|
-
return day;
|
|
937
|
-
}
|
|
938
|
-
function useWeekStart(own, locale) {
|
|
939
|
-
const readable = useHydrated();
|
|
940
|
-
const choice = useContext(LocaleContext);
|
|
941
|
-
if (own !== void 0) return own;
|
|
942
|
-
if (locale !== void 0) return weekStartOf(locale) ?? 1;
|
|
943
|
-
if (readable) return regionWeekStart();
|
|
944
|
-
return choice?.hasHeader ? firstDayFor(choice.spoken, choice.server) : 1;
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
// ../../showcase/src/components/Calendar/calendar-utils.ts
|
|
948
|
-
var formatters = localeCache(512);
|
|
949
|
-
function dtfFor(locale, options) {
|
|
950
|
-
return formatters(`${locale ?? ""}|${JSON.stringify(options)}`, () => new Intl.DateTimeFormat(locale, options));
|
|
951
|
-
}
|
|
952
|
-
function isSameDay(a, b) {
|
|
953
|
-
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
954
|
-
}
|
|
955
|
-
function isSameMonth(a, b) {
|
|
956
|
-
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();
|
|
957
|
-
}
|
|
958
|
-
function isWeekend(d) {
|
|
959
|
-
const day = d.getDay();
|
|
960
|
-
return day === 0 || day === 6;
|
|
961
|
-
}
|
|
962
|
-
function startOfDay(d) {
|
|
963
|
-
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
964
|
-
}
|
|
965
|
-
function startOfWeek(d, weekStartsOn = 0) {
|
|
966
|
-
const date = new Date(d);
|
|
967
|
-
const day = date.getDay();
|
|
968
|
-
const diff = (day - weekStartsOn + 7) % 7;
|
|
969
|
-
date.setDate(date.getDate() - diff);
|
|
970
|
-
return startOfDay(date);
|
|
971
|
-
}
|
|
972
|
-
function endOfWeek(d, weekStartsOn = 0) {
|
|
973
|
-
const start = startOfWeek(d, weekStartsOn);
|
|
974
|
-
const end = new Date(start);
|
|
975
|
-
end.setDate(end.getDate() + 6);
|
|
976
|
-
end.setHours(23, 59, 59, 999);
|
|
977
|
-
return end;
|
|
978
|
-
}
|
|
979
|
-
function addDays2(d, n) {
|
|
980
|
-
const result = new Date(d);
|
|
981
|
-
result.setDate(result.getDate() + n);
|
|
982
|
-
return result;
|
|
983
|
-
}
|
|
984
|
-
function addMonths(d, n) {
|
|
985
|
-
const result = new Date(d);
|
|
986
|
-
const day = result.getDate();
|
|
987
|
-
result.setDate(1);
|
|
988
|
-
result.setMonth(result.getMonth() + n);
|
|
989
|
-
result.setDate(Math.min(day, new Date(result.getFullYear(), result.getMonth() + 1, 0).getDate()));
|
|
990
|
-
return result;
|
|
991
|
-
}
|
|
992
|
-
function getMonthGrid(year, month, weekStartsOn = 0) {
|
|
993
|
-
const firstOfMonth = new Date(year, month, 1);
|
|
994
|
-
const gridStart = startOfWeek(firstOfMonth, weekStartsOn);
|
|
995
|
-
const weeks = [];
|
|
996
|
-
const current = new Date(gridStart);
|
|
997
|
-
for (let w = 0; w < 6; w++) {
|
|
998
|
-
const week = [];
|
|
999
|
-
for (let d = 0; d < 7; d++) {
|
|
1000
|
-
week.push(new Date(current));
|
|
1001
|
-
current.setDate(current.getDate() + 1);
|
|
1002
|
-
}
|
|
1003
|
-
weeks.push(week);
|
|
1004
|
-
}
|
|
1005
|
-
return weeks;
|
|
1006
|
-
}
|
|
1007
|
-
function getWeekDays(date, weekStartsOn = 0) {
|
|
1008
|
-
const start = startOfWeek(date, weekStartsOn);
|
|
1009
|
-
const days = [];
|
|
1010
|
-
for (let i = 0; i < 7; i++) {
|
|
1011
|
-
days.push(addDays2(start, i));
|
|
1012
|
-
}
|
|
1013
|
-
return days;
|
|
1014
|
-
}
|
|
1015
|
-
var DAY_MS = 864e5;
|
|
1016
|
-
function daysBetween(a, b) {
|
|
1017
|
-
return Math.round((startOfDay(b).getTime() - startOfDay(a).getTime()) / DAY_MS);
|
|
1018
|
-
}
|
|
1019
|
-
function eventSpan(e) {
|
|
1020
|
-
const first = startOfDay(e.start);
|
|
1021
|
-
if (!e.end) return { first, last: first };
|
|
1022
|
-
const lastInstant = e.allDay ? e.end : new Date(e.end.getTime() - 1);
|
|
1023
|
-
const last2 = startOfDay(lastInstant);
|
|
1024
|
-
return { first, last: last2 < first ? first : last2 };
|
|
1025
|
-
}
|
|
1026
|
-
function isBarEvent(e) {
|
|
1027
|
-
if (e.allDay) return true;
|
|
1028
|
-
if (!e.end) return false;
|
|
1029
|
-
const dayLater = new Date(e.start);
|
|
1030
|
-
dayLater.setDate(dayLater.getDate() + 1);
|
|
1031
|
-
return e.end.getTime() >= dayLater.getTime();
|
|
1032
|
-
}
|
|
1033
|
-
function getEventsForDay(events, date) {
|
|
1034
|
-
const day = startOfDay(date).getTime();
|
|
1035
|
-
return events.filter((e) => {
|
|
1036
|
-
const { first, last: last2 } = eventSpan(e);
|
|
1037
|
-
return first.getTime() <= day && day <= last2.getTime();
|
|
1038
|
-
});
|
|
1039
|
-
}
|
|
1040
|
-
function groupEventsByDay(events, from, to) {
|
|
1041
|
-
const out = /* @__PURE__ */ new Map();
|
|
1042
|
-
const lo = startOfDay(from), hi = startOfDay(to);
|
|
1043
|
-
for (const e of events) {
|
|
1044
|
-
const { first, last: last2 } = eventSpan(e);
|
|
1045
|
-
for (let day = first < lo ? lo : first; day <= last2 && day < hi; day = new Date(day.getFullYear(), day.getMonth(), day.getDate() + 1)) {
|
|
1046
|
-
const key = dayKey(day);
|
|
1047
|
-
const list2 = out.get(key);
|
|
1048
|
-
if (list2) list2.push(e);
|
|
1049
|
-
else out.set(key, [e]);
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
return out;
|
|
1053
|
-
}
|
|
1054
|
-
function dayPieces(events, date) {
|
|
1055
|
-
const dayStart = startOfDay(date);
|
|
1056
|
-
const next = new Date(dayStart.getFullYear(), dayStart.getMonth(), dayStart.getDate() + 1);
|
|
1057
|
-
const pieces = [];
|
|
1058
|
-
for (const event of events) {
|
|
1059
|
-
if (isBarEvent(event)) continue;
|
|
1060
|
-
const ownDayEnd = new Date(event.start.getFullYear(), event.start.getMonth(), event.start.getDate() + 1);
|
|
1061
|
-
const end = event.end && event.end > event.start ? event.end : new Date(Math.min(event.start.getTime() + 36e5, ownDayEnd.getTime()));
|
|
1062
|
-
const start = event.start < dayStart ? dayStart : event.start;
|
|
1063
|
-
const stop = end > next ? next : end;
|
|
1064
|
-
if (stop > start) pieces.push({ event, start, end: stop });
|
|
1065
|
-
}
|
|
1066
|
-
return pieces.sort((a, b) => a.start.getTime() - b.start.getTime() || b.end.getTime() - a.end.getTime());
|
|
1067
|
-
}
|
|
1068
|
-
function endDays(start, end) {
|
|
1069
|
-
return end > start ? daysBetween(start, new Date(end.getTime() - 1)) : daysBetween(start, end);
|
|
1070
|
-
}
|
|
1071
|
-
function makeDateWords(locale) {
|
|
1072
|
-
const dtf = (options) => dtfFor(locale, options);
|
|
1073
|
-
const twelveHour = () => /^h1[12]$/.test(dtf({ hour: "numeric" }).resolvedOptions().hourCycle ?? "");
|
|
1074
|
-
const timeOptions = () => ({ hour: twelveHour() ? "numeric" : "2-digit", minute: "2-digit" });
|
|
1075
|
-
const dayOffset = (days) => new Intl.NumberFormat(locale, { signDisplay: "always" }).format(days);
|
|
1076
|
-
function monthName2(month, width = "long") {
|
|
1077
|
-
return dtf({ month: width }).format(new Date(2026, month, 1));
|
|
1078
|
-
}
|
|
1079
|
-
function weekdayNames(weekStartsOn, width = "short") {
|
|
1080
|
-
const f = dtf({ weekday: width });
|
|
1081
|
-
return Array.from({ length: 7 }, (_, i) => f.format(new Date(2026, 0, 4 + weekStartsOn + i)));
|
|
1082
|
-
}
|
|
1083
|
-
function formatTime2(d) {
|
|
1084
|
-
return dtf(timeOptions()).format(d);
|
|
1085
|
-
}
|
|
1086
|
-
function formatHourLabel(hour) {
|
|
1087
|
-
const at = new Date(2026, 0, 5, hour);
|
|
1088
|
-
return twelveHour() ? dtf({ hour: "numeric" }).format(at) : dtf({ hour: "2-digit", minute: "2-digit" }).format(at);
|
|
1089
|
-
}
|
|
1090
|
-
function formatTimeRange(start, end) {
|
|
1091
|
-
if (!end) return formatTime2(start);
|
|
1092
|
-
const f = dtf(timeOptions());
|
|
1093
|
-
if (daysBetween(start, end) === 0) return f.formatRange(start, end);
|
|
1094
|
-
const sep = f.formatRangeToParts(start, end).find((p) => p.source === "shared" && p.type === "literal")?.value ?? " \u2013 ";
|
|
1095
|
-
const days = endDays(start, end);
|
|
1096
|
-
return days === 0 ? `${f.format(start)}${sep}${f.format(end)}` : `${f.format(start)}${sep}${f.format(end)} (${dayOffset(days)})`;
|
|
1097
|
-
}
|
|
1098
|
-
function speakTimeRange(start, end) {
|
|
1099
|
-
if (!end) return formatTime2(start);
|
|
1100
|
-
const days = endDays(start, end);
|
|
1101
|
-
const to = `${formatTime2(start)} to ${formatTime2(end)}`;
|
|
1102
|
-
return days === 0 ? to : days === 1 ? `${to} the next day` : `${to}, ${days} days later`;
|
|
1103
|
-
}
|
|
1104
|
-
function formatMonthYear(d) {
|
|
1105
|
-
return dtf({ month: "long", year: "numeric" }).format(d);
|
|
1106
|
-
}
|
|
1107
|
-
function formatDayLong(d) {
|
|
1108
|
-
return dtf({ weekday: "long", day: "numeric", month: "long", year: "numeric" }).format(d);
|
|
1109
|
-
}
|
|
1110
|
-
function formatDayShort(d) {
|
|
1111
|
-
return dtf({ weekday: "short", day: "numeric", month: "short" }).format(d);
|
|
1112
|
-
}
|
|
1113
|
-
function formatDayMedium(d) {
|
|
1114
|
-
return dtf({ day: "numeric", month: "short", year: "numeric" }).format(d);
|
|
1115
|
-
}
|
|
1116
|
-
function formatDayRange(start, end) {
|
|
1117
|
-
return dtf({ day: "numeric", month: "short", year: "numeric" }).formatRange(startOfDay(start), startOfDay(end));
|
|
1118
|
-
}
|
|
1119
|
-
function formatMonthRange(start, end) {
|
|
1120
|
-
return dtf({ month: "long", year: "numeric" }).formatRange(new Date(start.getFullYear(), start.getMonth(), 1), new Date(end.getFullYear(), end.getMonth(), 1));
|
|
1121
|
-
}
|
|
1122
|
-
function formatWeekRange(d, weekStartsOn = 0) {
|
|
1123
|
-
return dtf({ day: "numeric", month: "short", year: "numeric" }).formatRange(startOfWeek(d, weekStartsOn), startOfDay(endOfWeek(d, weekStartsOn)));
|
|
1124
|
-
}
|
|
1125
|
-
function formatEventWhen(e, spoken = false) {
|
|
1126
|
-
const { first, last: last2 } = eventSpan(e);
|
|
1127
|
-
const multiDay = last2 > first;
|
|
1128
|
-
if (e.allDay) {
|
|
1129
|
-
if (!multiDay) return spoken ? formatDayLong(first) : formatDayShort(first);
|
|
1130
|
-
return dtf(spoken ? { weekday: "long", day: "numeric", month: "long" } : { day: "numeric", month: "short" }).formatRange(first, last2);
|
|
1131
|
-
}
|
|
1132
|
-
if (!e.end || !isBarEvent(e)) {
|
|
1133
|
-
const day = spoken ? formatDayLong(e.start) : formatDayShort(e.start);
|
|
1134
|
-
const end = e.end && e.end > e.start ? e.end : void 0;
|
|
1135
|
-
return `${day}, ${spoken ? speakTimeRange(e.start, end) : formatTimeRange(e.start, end)}`;
|
|
1136
|
-
}
|
|
1137
|
-
return dtf({ weekday: "short", day: "numeric", month: "short", hour: "numeric", minute: "2-digit" }).formatRange(e.start, e.end);
|
|
1138
|
-
}
|
|
1139
|
-
return { monthName: monthName2, weekdayNames, formatTime: formatTime2, formatHourLabel, formatTimeRange, speakTimeRange, formatMonthYear, formatDayLong, formatDayShort, formatDayMedium, formatDayRange, formatMonthRange, formatWeekRange, formatEventWhen };
|
|
1140
|
-
}
|
|
1141
|
-
var wordsByLocale = localeCache(32);
|
|
1142
|
-
function dateWords(locale) {
|
|
1143
|
-
return wordsByLocale(locale ?? "", () => makeDateWords(locale));
|
|
1144
|
-
}
|
|
1145
|
-
function useDateWords() {
|
|
1146
|
-
return dateWords(useFormatLocale());
|
|
1147
|
-
}
|
|
1148
|
-
function layoutWeek(events, days, capacity) {
|
|
1149
|
-
const weekStart = startOfDay(days[0]);
|
|
1150
|
-
const weekEnd = startOfDay(days[days.length - 1]);
|
|
1151
|
-
const items = [];
|
|
1152
|
-
for (const event of events) {
|
|
1153
|
-
const { first, last: last2 } = eventSpan(event);
|
|
1154
|
-
if (last2 < weekStart || first > weekEnd) continue;
|
|
1155
|
-
items.push({
|
|
1156
|
-
event,
|
|
1157
|
-
startCol: Math.max(0, daysBetween(weekStart, first)),
|
|
1158
|
-
endCol: Math.min(days.length - 1, daysBetween(weekStart, last2)),
|
|
1159
|
-
before: first < weekStart,
|
|
1160
|
-
after: last2 > weekEnd,
|
|
1161
|
-
length: daysBetween(first, last2) + 1
|
|
1162
|
-
});
|
|
1163
|
-
}
|
|
1164
|
-
items.sort((a, b) => {
|
|
1165
|
-
const barA = isBarEvent(a.event) || a.length > 1, barB = isBarEvent(b.event) || b.length > 1;
|
|
1166
|
-
if (barA !== barB) return barA ? -1 : 1;
|
|
1167
|
-
if (barA && a.length !== b.length) return b.length - a.length;
|
|
1168
|
-
return a.event.start.getTime() - b.event.start.getTime() || a.event.title.localeCompare(b.event.title);
|
|
1169
|
-
});
|
|
1170
|
-
const taken = [];
|
|
1171
|
-
const laneOf = /* @__PURE__ */ new Map();
|
|
1172
|
-
for (const item of items) {
|
|
1173
|
-
let lane = 0;
|
|
1174
|
-
while (Array.from({ length: item.endCol - item.startCol + 1 }, (_, k) => taken[lane]?.[item.startCol + k]).some(Boolean)) lane++;
|
|
1175
|
-
taken[lane] ??= [];
|
|
1176
|
-
for (let c = item.startCol; c <= item.endCol; c++) taken[lane][c] = true;
|
|
1177
|
-
laneOf.set(item, lane);
|
|
1178
|
-
}
|
|
1179
|
-
const cap = Math.max(1, capacity);
|
|
1180
|
-
const overflow = days.map((_, c) => items.some((it) => laneOf.get(it) >= cap && it.startCol <= c && c <= it.endCol));
|
|
1181
|
-
const more = days.map((_, c) => overflow[c] ? items.filter((it) => laneOf.get(it) >= cap - 1 && it.startCol <= c && c <= it.endCol).map((it) => it.event) : []);
|
|
1182
|
-
const segments = [];
|
|
1183
|
-
for (const item of items) {
|
|
1184
|
-
const lane = laneOf.get(item);
|
|
1185
|
-
if (lane >= cap) continue;
|
|
1186
|
-
if (lane < cap - 1) {
|
|
1187
|
-
segments.push({ event: item.event, startCol: item.startCol, span: item.endCol - item.startCol + 1, lane, continuesBefore: item.before, continuesAfter: item.after });
|
|
1188
|
-
continue;
|
|
1189
|
-
}
|
|
1190
|
-
let runStart = -1;
|
|
1191
|
-
for (let c = item.startCol; c <= item.endCol + 1; c++) {
|
|
1192
|
-
const free = c <= item.endCol && !overflow[c];
|
|
1193
|
-
if (free && runStart < 0) runStart = c;
|
|
1194
|
-
if (!free && runStart >= 0) {
|
|
1195
|
-
segments.push({ event: item.event, startCol: runStart, span: c - runStart, lane, continuesBefore: runStart > item.startCol || item.before, continuesAfter: c - 1 < item.endCol || item.after });
|
|
1196
|
-
runStart = -1;
|
|
1197
|
-
}
|
|
1198
|
-
}
|
|
1199
|
-
}
|
|
1200
|
-
const lanes = Math.min(cap, taken.length);
|
|
1201
|
-
return { segments, more, lanes };
|
|
1202
|
-
}
|
|
1203
|
-
function layoutPieces(pieces, minMinutes = 0) {
|
|
1204
|
-
const out = [];
|
|
1205
|
-
let group = [];
|
|
1206
|
-
let columnEnds = [];
|
|
1207
|
-
let groupEnd = -Infinity;
|
|
1208
|
-
const close = () => {
|
|
1209
|
-
for (const placed of group) placed.columns = columnEnds.length;
|
|
1210
|
-
out.push(...group);
|
|
1211
|
-
group = [];
|
|
1212
|
-
columnEnds = [];
|
|
1213
|
-
};
|
|
1214
|
-
for (const piece of pieces) {
|
|
1215
|
-
const at = piece.start.getTime();
|
|
1216
|
-
const end = Math.max(piece.end.getTime(), at + minMinutes * 6e4);
|
|
1217
|
-
if (group.length && at >= groupEnd) close();
|
|
1218
|
-
let column = columnEnds.findIndex((e) => e <= at);
|
|
1219
|
-
if (column < 0) column = columnEnds.push(0) - 1;
|
|
1220
|
-
columnEnds[column] = end;
|
|
1221
|
-
groupEnd = Math.max(group.length ? groupEnd : -Infinity, end);
|
|
1222
|
-
group.push({ piece, column, columns: 0 });
|
|
1223
|
-
}
|
|
1224
|
-
if (group.length) close();
|
|
1225
|
-
return out;
|
|
1226
|
-
}
|
|
1227
|
-
function timeToFraction(d) {
|
|
1228
|
-
return (d.getHours() * 60 + d.getMinutes()) / (24 * 60);
|
|
1229
|
-
}
|
|
1230
606
|
var CONTROL_HEIGHT2 = {
|
|
1231
607
|
sm: "h-[var(--ds-control-height-sm)]",
|
|
1232
608
|
md: "h-[var(--ds-control-height-md)]",
|
|
@@ -1237,552 +613,88 @@ var TEXT_SIZE2 = {
|
|
|
1237
613
|
md: "text-sm",
|
|
1238
614
|
lg: "text-base"
|
|
1239
615
|
};
|
|
1240
|
-
var
|
|
1241
|
-
"
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
"
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
"
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
616
|
+
var DEFAULT_DATE_RANGE_PRESETS = [
|
|
617
|
+
{ label: "Today", range: () => {
|
|
618
|
+
const t = startOfDay(/* @__PURE__ */ new Date());
|
|
619
|
+
return { start: t, end: t };
|
|
620
|
+
} },
|
|
621
|
+
{ label: "Last 7 days", range: () => {
|
|
622
|
+
const t = startOfDay(/* @__PURE__ */ new Date());
|
|
623
|
+
return { start: addDays(t, -6), end: t };
|
|
624
|
+
} },
|
|
625
|
+
{ label: "Last 30 days", range: () => {
|
|
626
|
+
const t = startOfDay(/* @__PURE__ */ new Date());
|
|
627
|
+
return { start: addDays(t, -29), end: t };
|
|
628
|
+
} },
|
|
629
|
+
{ label: "This month", range: () => {
|
|
630
|
+
const t = /* @__PURE__ */ new Date();
|
|
631
|
+
return { start: new Date(t.getFullYear(), t.getMonth(), 1), end: startOfDay(t) };
|
|
632
|
+
} },
|
|
633
|
+
{ label: "Last month", range: () => {
|
|
634
|
+
const t = /* @__PURE__ */ new Date();
|
|
635
|
+
return { start: new Date(t.getFullYear(), t.getMonth() - 1, 1), end: new Date(t.getFullYear(), t.getMonth(), 0) };
|
|
636
|
+
} }
|
|
1253
637
|
];
|
|
1254
|
-
function
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
if (monthIndex2 < 0 || monthIndex2 > 11 || day < 1) return null;
|
|
1274
|
-
const d = new Date(year, monthIndex2, day);
|
|
1275
|
-
return d.getFullYear() === year && d.getMonth() === monthIndex2 && d.getDate() === day ? d : null;
|
|
1276
|
-
}
|
|
1277
|
-
function monthIndex(name, locale) {
|
|
1278
|
-
const typed = name.toLocaleLowerCase().replace(/\.$/, "");
|
|
1279
|
-
const fold = (m) => m.toLocaleLowerCase().replace(/\.$/, "");
|
|
1280
|
-
const { monthName: monthName2 } = dateWords(locale);
|
|
1281
|
-
const lists = [ENGLISH_MONTHS, Array.from({ length: 12 }, (_, i) => fold(monthName2(i, "long"))), Array.from({ length: 12 }, (_, i) => fold(monthName2(i, "short")))];
|
|
1282
|
-
for (const list2 of lists) {
|
|
1283
|
-
const i = list2.findIndex((m) => m.startsWith(typed) || typed.length >= 3 && typed.startsWith(m));
|
|
1284
|
-
if (i >= 0) return i;
|
|
1285
|
-
}
|
|
1286
|
-
return -1;
|
|
1287
|
-
}
|
|
1288
|
-
function parseTypedDate(text, dayFirst = localeDayFirst(), locale = formatLocale()) {
|
|
1289
|
-
const t = text.trim().replace(/\s+/g, " ");
|
|
1290
|
-
if (!t) return null;
|
|
1291
|
-
let m = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(t);
|
|
1292
|
-
if (m) return validDate(Number(m[1]), Number(m[2]) - 1, Number(m[3]));
|
|
1293
|
-
m = /^(\p{L}{3,})\.?\s+(\d{1,2}),?\s+(\d{4})$/u.exec(t);
|
|
1294
|
-
if (m) {
|
|
1295
|
-
const mi = monthIndex(m[1], locale);
|
|
1296
|
-
return mi < 0 ? null : validDate(Number(m[3]), mi, Number(m[2]));
|
|
1297
|
-
}
|
|
1298
|
-
m = /^(\d{1,2})\.?\s+(\p{L}{3,})\.?,?\s+(\d{4})$/u.exec(t);
|
|
1299
|
-
if (m) {
|
|
1300
|
-
const mi = monthIndex(m[2], locale);
|
|
1301
|
-
return mi < 0 ? null : validDate(Number(m[3]), mi, Number(m[1]));
|
|
1302
|
-
}
|
|
1303
|
-
m = /^(\d{1,2})[/.-](\d{1,2})[/.-](\d{2,4})$/.exec(t);
|
|
1304
|
-
if (m) {
|
|
1305
|
-
const a = Number(m[1]), b = Number(m[2]);
|
|
1306
|
-
const year = m[3].length === 2 ? 2e3 + Number(m[3]) : Number(m[3]);
|
|
1307
|
-
const [day, month] = a > 12 ? [a, b] : b > 12 ? [b, a] : dayFirst ? [a, b] : [b, a];
|
|
1308
|
-
return validDate(year, month - 1, day);
|
|
1309
|
-
}
|
|
1310
|
-
return null;
|
|
1311
|
-
}
|
|
1312
|
-
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 }) {
|
|
638
|
+
function DateRangePicker({
|
|
639
|
+
value,
|
|
640
|
+
onChange: onChangeProp,
|
|
641
|
+
placeholder = "Pick a date range",
|
|
642
|
+
disabled,
|
|
643
|
+
error = false,
|
|
644
|
+
label,
|
|
645
|
+
id,
|
|
646
|
+
className,
|
|
647
|
+
ref,
|
|
648
|
+
container,
|
|
649
|
+
min,
|
|
650
|
+
max,
|
|
651
|
+
disabledDates,
|
|
652
|
+
presets = DEFAULT_DATE_RANGE_PRESETS,
|
|
653
|
+
weekStartsOn: weekStartsOnProp,
|
|
654
|
+
size: sizeProp,
|
|
655
|
+
...wiring
|
|
656
|
+
}) {
|
|
1313
657
|
const weekStartsOn = useWeekStart(weekStartsOnProp);
|
|
1314
|
-
const
|
|
1315
|
-
const { formatDayLong, formatMonthYear, weekdayNames } = useDateWords();
|
|
658
|
+
const { weekdayNames, formatDayLong, formatDayMedium, formatDayRange, formatMonthRange, formatMonthYear } = useDateWords();
|
|
1316
659
|
const hydrated = useHydrated();
|
|
1317
|
-
const
|
|
660
|
+
const now = useToday();
|
|
1318
661
|
const onChange = useReportedChange(onChangeProp, value);
|
|
1319
662
|
const contextSize = useContext(ControlSizeContext);
|
|
1320
663
|
const size = sizeProp ?? contextSize ?? "md";
|
|
1321
664
|
const [open, setOpen] = useState(false);
|
|
665
|
+
const [viewDate, setViewDate] = useState(() => value.start ?? /* @__PURE__ */ new Date());
|
|
1322
666
|
const [hover, setHover] = useState(null);
|
|
1323
|
-
const [viewDate, setViewDate] = useState(() => value ?? range2?.start ?? range2?.end ?? /* @__PURE__ */ new Date());
|
|
1324
667
|
const triggerRef = useRef(null);
|
|
1325
668
|
const buttonRef = useRef(null);
|
|
1326
669
|
const panelRef = useRef(null);
|
|
1327
|
-
const
|
|
670
|
+
const isPhone = useBreakpoint("sm");
|
|
671
|
+
const presetEdges = useScrollEdges({ enabled: isPhone });
|
|
672
|
+
useRevealFocus(presetEdges.elRef, isPhone);
|
|
1328
673
|
const generatedId = useId();
|
|
1329
674
|
const control = useFieldControl({ ...wiring, id, error: error || void 0 }, { requiredInDescription: true });
|
|
1330
675
|
useInputModality();
|
|
1331
|
-
const
|
|
1332
|
-
const
|
|
1333
|
-
const year = viewDate.getFullYear();
|
|
1334
|
-
const month = viewDate.getMonth();
|
|
1335
|
-
const daysInMonth = getDaysInMonth(year, month);
|
|
1336
|
-
const firstDay = getFirstDayOfWeek(year, month, weekStartsOn);
|
|
1337
|
-
const startOf = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
1338
|
-
const isDisabledDay = (d) => !!min && d < startOf(min) || !!max && d > startOf(max);
|
|
1339
|
-
const [focusDate, setFocusDate] = useState(() => startOf(value ?? range2?.start ?? range2?.end ?? /* @__PURE__ */ new Date()));
|
|
1340
|
-
const [prevOpen, setPrevOpen] = useState(open);
|
|
1341
|
-
if (open !== prevOpen) {
|
|
1342
|
-
setPrevOpen(open);
|
|
1343
|
-
if (open) {
|
|
1344
|
-
const start = startOf(value ?? range2?.start ?? range2?.end ?? today ?? /* @__PURE__ */ new Date());
|
|
1345
|
-
setFocusDate(start);
|
|
1346
|
-
setViewDate(new Date(start.getFullYear(), start.getMonth(), 1));
|
|
1347
|
-
}
|
|
1348
|
-
}
|
|
1349
|
-
const showDay = (d) => {
|
|
1350
|
-
setFocusDate(d);
|
|
1351
|
-
if (d.getFullYear() !== year || d.getMonth() !== month) setViewDate(new Date(d.getFullYear(), d.getMonth(), 1));
|
|
1352
|
-
};
|
|
1353
|
-
const grid = useGridKeyboard({
|
|
1354
|
-
container: gridRef,
|
|
1355
|
-
active: focusDate,
|
|
1356
|
-
setActive: showDay,
|
|
1357
|
-
keyOf: dayKey,
|
|
1358
|
-
move: (from, e) => moveDay(from, e.key, e.shiftKey, weekStartsOn)
|
|
1359
|
-
});
|
|
1360
|
-
const prevMonth = () => {
|
|
1361
|
-
setViewDate(new Date(year, month - 1, 1));
|
|
1362
|
-
setFocusDate(addMonthsClamped(focusDate, -1));
|
|
1363
|
-
};
|
|
1364
|
-
const nextMonth = () => {
|
|
1365
|
-
setViewDate(new Date(year, month + 1, 1));
|
|
1366
|
-
setFocusDate(addMonthsClamped(focusDate, 1));
|
|
1367
|
-
};
|
|
1368
|
-
const { isTop: isTopLayer, returnFocus } = usePopupFocus(open, { trigger: buttonRef, panel: panelRef, close: () => setOpen(false), tabExits: "edges" });
|
|
1369
|
-
const focusActiveDay = useLatest(grid.focusActive);
|
|
1370
|
-
useEffect(() => {
|
|
1371
|
-
if (!open) return;
|
|
1372
|
-
const raf = requestAnimationFrame(() => focusActiveDay.current());
|
|
1373
|
-
return () => cancelAnimationFrame(raf);
|
|
1374
|
-
}, [open, focusActiveDay]);
|
|
1375
|
-
const choose = (d) => {
|
|
1376
|
-
returnFocus();
|
|
1377
|
-
onChange(d);
|
|
1378
|
-
setOpen(false);
|
|
1379
|
-
};
|
|
676
|
+
const triggerId = control.id ?? generatedId;
|
|
677
|
+
const locale = useFormatLocale();
|
|
1380
678
|
const dayFirst = useMemo(() => localeDayFirst(locale), [locale]);
|
|
1381
|
-
const
|
|
1382
|
-
|
|
1383
|
-
const
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
const segmentRefs = useRef([]);
|
|
1391
|
-
const focusSegment = (i) => {
|
|
1392
|
-
segmentRefs.current[Math.max(0, Math.min(specs.length - 1, i))]?.focus();
|
|
1393
|
-
};
|
|
1394
|
-
useEffect(() => {
|
|
1395
|
-
if (!open) return;
|
|
1396
|
-
const handler = (e) => {
|
|
1397
|
-
const t = e.target;
|
|
1398
|
-
if (triggerRef.current?.contains(t) || panelRef.current?.contains(t)) return;
|
|
1399
|
-
setOpen(false);
|
|
1400
|
-
};
|
|
1401
|
-
const keyHandler = (e) => {
|
|
1402
|
-
if (e.key !== "Escape" || e.defaultPrevented || !isTopLayer()) return;
|
|
1403
|
-
e.preventDefault();
|
|
1404
|
-
returnFocus();
|
|
1405
|
-
setOpen(false);
|
|
679
|
+
const focusPart = useRef(() => {
|
|
680
|
+
});
|
|
681
|
+
const [typedInvalid, setTypedInvalid] = useState(false);
|
|
682
|
+
useLayoutEffect(() => {
|
|
683
|
+
const panel = panelRef.current;
|
|
684
|
+
if (!open || !isPhone || !panel) return;
|
|
685
|
+
const fit = () => {
|
|
686
|
+
const field = triggerRef.current;
|
|
687
|
+
if (field) panel.style.width = `${field.getBoundingClientRect().width}px`;
|
|
1406
688
|
};
|
|
1407
|
-
|
|
1408
|
-
|
|
689
|
+
fit();
|
|
690
|
+
window.addEventListener("resize", fit);
|
|
1409
691
|
return () => {
|
|
1410
|
-
|
|
1411
|
-
|
|
692
|
+
window.removeEventListener("resize", fit);
|
|
693
|
+
panel.style.width = "";
|
|
1412
694
|
};
|
|
1413
|
-
}, [open,
|
|
1414
|
-
const [typedInvalid, setTypedInvalid] = useState(false);
|
|
1415
|
-
const commitIfComplete = (next) => {
|
|
1416
|
-
if (next.day === null || next.month === null || next.year === null) {
|
|
1417
|
-
setTypedInvalid(false);
|
|
1418
|
-
return;
|
|
1419
|
-
}
|
|
1420
|
-
const d = validDate(next.year, next.month - 1, next.day);
|
|
1421
|
-
const ok = !!d && (!min || d >= min) && (!max || d <= max);
|
|
1422
|
-
setTypedInvalid(!ok);
|
|
1423
|
-
if (d && ok && !(value && isSameDay2(value, d))) {
|
|
1424
|
-
lastCommitted.current = d.getTime();
|
|
1425
|
-
onChange(d);
|
|
1426
|
-
setViewDate(d);
|
|
1427
|
-
}
|
|
1428
|
-
};
|
|
1429
|
-
const setSegment = (key, v, commit2 = true) => {
|
|
1430
|
-
setSegs((cur) => {
|
|
1431
|
-
const next = { ...cur, [key]: v };
|
|
1432
|
-
if (commit2) commitIfComplete(next);
|
|
1433
|
-
return next;
|
|
1434
|
-
});
|
|
1435
|
-
};
|
|
1436
|
-
const applyTyped = (text) => {
|
|
1437
|
-
const d = parseTypedDate(text, dayFirst, locale);
|
|
1438
|
-
if (!d) return;
|
|
1439
|
-
const next = { day: d.getDate(), month: d.getMonth() + 1, year: d.getFullYear() };
|
|
1440
|
-
setSegs(next);
|
|
1441
|
-
setBuffers({});
|
|
1442
|
-
commitIfComplete(next);
|
|
1443
|
-
};
|
|
1444
|
-
const onSegmentKeyDown = (e, index, spec) => {
|
|
1445
|
-
const key = e.key;
|
|
1446
|
-
if (key === "Tab" || key === "Shift" || key === "Escape" || key.startsWith("F")) return;
|
|
1447
|
-
e.preventDefault();
|
|
1448
|
-
const k = spec.key;
|
|
1449
|
-
const clearBuffer = () => setBuffers((b) => ({ ...b, [k]: "" }));
|
|
1450
|
-
if (key === "ArrowLeft") {
|
|
1451
|
-
focusSegment(index - 1);
|
|
1452
|
-
return;
|
|
1453
|
-
}
|
|
1454
|
-
if (key === "ArrowRight") {
|
|
1455
|
-
focusSegment(index + 1);
|
|
1456
|
-
return;
|
|
1457
|
-
}
|
|
1458
|
-
if (key === "ArrowUp" || key === "ArrowDown") {
|
|
1459
|
-
clearBuffer();
|
|
1460
|
-
setSegment(k, stepValue(spec, segs[k], key === "ArrowUp" ? 1 : -1));
|
|
1461
|
-
return;
|
|
1462
|
-
}
|
|
1463
|
-
if (key === "Home") {
|
|
1464
|
-
clearBuffer();
|
|
1465
|
-
setSegment(k, spec.min);
|
|
1466
|
-
return;
|
|
1467
|
-
}
|
|
1468
|
-
if (key === "End") {
|
|
1469
|
-
clearBuffer();
|
|
1470
|
-
setSegment(k, spec.max);
|
|
1471
|
-
return;
|
|
1472
|
-
}
|
|
1473
|
-
if (key === "Backspace" || key === "Delete") {
|
|
1474
|
-
if (segs[k] === null && !buffers[k]) {
|
|
1475
|
-
focusSegment(index - 1);
|
|
1476
|
-
return;
|
|
1477
|
-
}
|
|
1478
|
-
clearBuffer();
|
|
1479
|
-
setSegment(k, null, false);
|
|
1480
|
-
return;
|
|
1481
|
-
}
|
|
1482
|
-
if (/^\d$/.test(key)) {
|
|
1483
|
-
const r = typeDigit(spec, buffers[k] ?? "", key);
|
|
1484
|
-
setBuffers((b) => ({ ...b, [k]: r.advance ? "" : r.buffer }));
|
|
1485
|
-
setSegment(k, r.value);
|
|
1486
|
-
if (r.advance) focusSegment(index + 1);
|
|
1487
|
-
}
|
|
1488
|
-
};
|
|
1489
|
-
const drawn = hydrated ? segs : NO_SEGMENTS;
|
|
1490
|
-
const shown = (spec) => {
|
|
1491
|
-
const k = spec.key;
|
|
1492
|
-
const b = buffers[k];
|
|
1493
|
-
if (b && drawn[k] === null) return b;
|
|
1494
|
-
if (drawn[k] === null) return spec.placeholder;
|
|
1495
|
-
return k === "year" ? String(drawn[k]) : pad2(drawn[k]);
|
|
1496
|
-
};
|
|
1497
|
-
const selectDay = (day) => {
|
|
1498
|
-
const d = new Date(year, month, day);
|
|
1499
|
-
if (isDisabledDay(d)) return;
|
|
1500
|
-
choose(d);
|
|
1501
|
-
};
|
|
1502
|
-
const rangeA = range2?.start ?? null;
|
|
1503
|
-
const rangeB = range2?.end ?? null;
|
|
1504
|
-
const otherEnd = value ? rangeA && !isSameDay2(rangeA, value) ? rangeA : rangeB : rangeA ?? rangeB;
|
|
1505
|
-
const thisEnd = value ?? (otherEnd && hover ? hover : null);
|
|
1506
|
-
const [bandStart, bandEnd] = otherEnd && thisEnd ? otherEnd <= thisEnd ? [otherEnd, thisEnd] : [thisEnd, otherEnd] : [null, null];
|
|
1507
|
-
const inBand = (d) => !!(bandStart && bandEnd && d > bandStart && d < bandEnd);
|
|
1508
|
-
const cells = [];
|
|
1509
|
-
for (let i = 0; i < firstDay; i++) cells.push(null);
|
|
1510
|
-
for (let d = 1; d <= daysInMonth; d++) cells.push(d);
|
|
1511
|
-
while (cells.length % 7) cells.push(null);
|
|
1512
|
-
const weeks = [];
|
|
1513
|
-
for (let i = 0; i < cells.length; i += 7) weeks.push(cells.slice(i, i + 7));
|
|
1514
|
-
return /* @__PURE__ */ jsxs("div", { ref, className: cn(className), children: [
|
|
1515
|
-
label && /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "block text-sm font-medium text-[var(--ds-text-primary)] mb-ds-1", children: label }),
|
|
1516
|
-
control.requiredNote,
|
|
1517
|
-
/* @__PURE__ */ jsxs(
|
|
1518
|
-
"div",
|
|
1519
|
-
{
|
|
1520
|
-
ref: triggerRef,
|
|
1521
|
-
"data-date-field": "",
|
|
1522
|
-
role: "group",
|
|
1523
|
-
id: inputId,
|
|
1524
|
-
"aria-label": control.labelId ? void 0 : label ?? "Date",
|
|
1525
|
-
"aria-labelledby": control.labelId,
|
|
1526
|
-
"aria-describedby": control.describedBy,
|
|
1527
|
-
"aria-description": !value ? placeholder : void 0,
|
|
1528
|
-
"aria-invalid": control.invalid || typedInvalid || void 0,
|
|
1529
|
-
onPaste: (e) => {
|
|
1530
|
-
const text = e.clipboardData.getData("text");
|
|
1531
|
-
if (text) {
|
|
1532
|
-
e.preventDefault();
|
|
1533
|
-
applyTyped(text);
|
|
1534
|
-
}
|
|
1535
|
-
},
|
|
1536
|
-
className: cn(
|
|
1537
|
-
"flex items-center gap-ds-2 w-full",
|
|
1538
|
-
CONTROL_HEIGHT2[size],
|
|
1539
|
-
TEXT_SIZE2[size],
|
|
1540
|
-
"border-[length:var(--ds-border-width)]",
|
|
1541
|
-
control.invalid || typedInvalid ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
|
|
1542
|
-
"bg-[var(--ds-input-bg)] rounded-[var(--ds-radius-md)]",
|
|
1543
|
-
"shadow-[var(--ds-input-shadow)]",
|
|
1544
|
-
"transition-colors",
|
|
1545
|
-
"px-ds-3 py-ds-2",
|
|
1546
|
-
!control.invalid && !disabled && !open && "hover:border-[var(--ds-input-border-hover)]",
|
|
1547
|
-
open && (control.invalid || typedInvalid ? ERROR_ACTIVE_RING : ACTIVE_RING),
|
|
1548
|
-
// the segments mark which part has focus (their tint); the field draws the focus (a hover keeps its border)
|
|
1549
|
-
control.invalid || typedInvalid ? ERROR_FOCUS_WITHIN_RING : FIELD_FOCUS_WITHIN_RING,
|
|
1550
|
-
disabled && "opacity-disabled cursor-not-allowed",
|
|
1551
|
-
"text-[var(--ds-text-primary)]"
|
|
1552
|
-
),
|
|
1553
|
-
children: [
|
|
1554
|
-
/* @__PURE__ */ jsx(Icon, { name: "calendar", size: 14, className: "text-[var(--ds-text-muted)] shrink-0" }),
|
|
1555
|
-
/* @__PURE__ */ jsx("div", { className: "flex items-center min-w-0 flex-1 tabular-nums", onClick: () => focusSegment(0), children: specs.map((spec, i) => {
|
|
1556
|
-
const k = spec.key;
|
|
1557
|
-
return /* @__PURE__ */ jsxs("span", { className: "contents", children: [
|
|
1558
|
-
i > 0 && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "px-[1px] text-[var(--ds-text-muted)]", children: "/" }),
|
|
1559
|
-
/* @__PURE__ */ jsx(
|
|
1560
|
-
"span",
|
|
1561
|
-
{
|
|
1562
|
-
ref: (el) => {
|
|
1563
|
-
segmentRefs.current[i] = el;
|
|
1564
|
-
},
|
|
1565
|
-
role: "spinbutton",
|
|
1566
|
-
tabIndex: disabled ? -1 : 0,
|
|
1567
|
-
"data-segment": spec.key,
|
|
1568
|
-
"aria-label": spec.label,
|
|
1569
|
-
"aria-valuemin": spec.min,
|
|
1570
|
-
"aria-valuemax": spec.max,
|
|
1571
|
-
"aria-valuenow": drawn[k] ?? void 0,
|
|
1572
|
-
"aria-valuetext": drawn[k] === null ? "empty" : String(drawn[k]),
|
|
1573
|
-
onKeyDown: (e) => onSegmentKeyDown(e, i, spec),
|
|
1574
|
-
onClick: (e) => e.stopPropagation(),
|
|
1575
|
-
className: cn("rounded-[var(--ds-radius-sm)] px-[2px] outline-none focus:bg-[var(--ds-accent-subtle)] focus:text-[var(--ds-accent-ink)] cursor-text", drawn[k] === null && !buffers[k] && "text-[var(--ds-text-muted)]"),
|
|
1576
|
-
children: shown(spec)
|
|
1577
|
-
}
|
|
1578
|
-
)
|
|
1579
|
-
] }, spec.key);
|
|
1580
|
-
}) }),
|
|
1581
|
-
/* @__PURE__ */ jsx(
|
|
1582
|
-
"button",
|
|
1583
|
-
{
|
|
1584
|
-
ref: buttonRef,
|
|
1585
|
-
type: "button",
|
|
1586
|
-
"aria-label": "Choose a date",
|
|
1587
|
-
"aria-haspopup": "dialog",
|
|
1588
|
-
"aria-expanded": open,
|
|
1589
|
-
onClick: () => !disabled && setOpen(!open),
|
|
1590
|
-
disabled,
|
|
1591
|
-
className: cn("shrink-0 -mr-ds-1 rounded-[var(--ds-radius-sm)] text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] disabled:cursor-not-allowed", FOCUS_RING),
|
|
1592
|
-
children: /* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: 14 })
|
|
1593
|
-
}
|
|
1594
|
-
)
|
|
1595
|
-
]
|
|
1596
|
-
}
|
|
1597
|
-
),
|
|
1598
|
-
open && createPortal(
|
|
1599
|
-
/* @__PURE__ */ jsxs(
|
|
1600
|
-
"div",
|
|
1601
|
-
{
|
|
1602
|
-
ref: panelRef,
|
|
1603
|
-
role: "dialog",
|
|
1604
|
-
"aria-label": "Choose a date",
|
|
1605
|
-
tabIndex: -1,
|
|
1606
|
-
className: cn(
|
|
1607
|
-
"fixed z-[var(--ds-z-popover)] w-[280px] outline-none",
|
|
1608
|
-
"bg-[var(--ds-bg-surface-elevated)]",
|
|
1609
|
-
"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]",
|
|
1610
|
-
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
1611
|
-
"rounded-[var(--ds-radius-md)]",
|
|
1612
|
-
"shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]"
|
|
1613
|
-
),
|
|
1614
|
-
style: { top: pos.top, left: pos.left },
|
|
1615
|
-
children: [
|
|
1616
|
-
/* @__PURE__ */ jsxs(
|
|
1617
|
-
"div",
|
|
1618
|
-
{
|
|
1619
|
-
className: "flex items-center justify-between bg-[var(--ds-bg-muted)] rounded-t-[var(--ds-radius-md)]",
|
|
1620
|
-
style: { padding: "var(--ds-space-2) var(--ds-space-3)" },
|
|
1621
|
-
children: [
|
|
1622
|
-
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: prevMonth, "aria-label": "Previous month", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14, className: "rotate-180" }) }),
|
|
1623
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-[var(--ds-text-primary)]", children: formatMonthYear(viewDate) }),
|
|
1624
|
-
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: nextMonth, "aria-label": "Next month", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14 }) })
|
|
1625
|
-
]
|
|
1626
|
-
}
|
|
1627
|
-
),
|
|
1628
|
-
/* @__PURE__ */ jsxs(
|
|
1629
|
-
"div",
|
|
1630
|
-
{
|
|
1631
|
-
ref: gridRef,
|
|
1632
|
-
role: "grid",
|
|
1633
|
-
"aria-label": formatMonthYear(viewDate),
|
|
1634
|
-
onKeyDown: grid.onKeyDown,
|
|
1635
|
-
className: "flex flex-col gap-[4px] tabular-nums",
|
|
1636
|
-
style: { padding: "var(--ds-space-2) var(--ds-space-3)" },
|
|
1637
|
-
children: [
|
|
1638
|
-
/* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 gap-[4px] 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)) }),
|
|
1639
|
-
weeks.map((week, w) => /* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 gap-[4px]", onMouseLeave: () => setHover(null), children: week.map((day, i) => {
|
|
1640
|
-
if (day === null) return /* @__PURE__ */ jsx("div", { role: "gridcell" }, `empty-${i}`);
|
|
1641
|
-
const dateObj = new Date(year, month, day);
|
|
1642
|
-
const isSelected = !!value && isSameDay2(dateObj, value);
|
|
1643
|
-
const isOtherEnd = !!otherEnd && isSameDay2(dateObj, otherEnd);
|
|
1644
|
-
const isToday = today !== null && isSameDay2(dateObj, today);
|
|
1645
|
-
const between = inBand(dateObj);
|
|
1646
|
-
const dis = isDisabledDay(dateObj);
|
|
1647
|
-
return /* @__PURE__ */ jsx(
|
|
1648
|
-
"button",
|
|
1649
|
-
{
|
|
1650
|
-
type: "button",
|
|
1651
|
-
role: "gridcell",
|
|
1652
|
-
"data-grid-key": dayKey(dateObj),
|
|
1653
|
-
tabIndex: grid.tabIndexOf(dateObj),
|
|
1654
|
-
"aria-disabled": dis || void 0,
|
|
1655
|
-
onClick: () => selectDay(day),
|
|
1656
|
-
onFocus: () => {
|
|
1657
|
-
if (!isSameDay2(dateObj, focusDate)) setFocusDate(dateObj);
|
|
1658
|
-
},
|
|
1659
|
-
onMouseEnter: () => setHover(dateObj),
|
|
1660
|
-
"aria-selected": isSelected,
|
|
1661
|
-
"aria-current": isToday ? "date" : void 0,
|
|
1662
|
-
"aria-label": formatDayLong(dateObj),
|
|
1663
|
-
className: cn(
|
|
1664
|
-
"w-full aspect-square flex items-center justify-center text-xs",
|
|
1665
|
-
"transition-colors cursor-pointer",
|
|
1666
|
-
FOCUS_RING,
|
|
1667
|
-
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-ink)] text-[var(--ds-accent-ink)] font-medium rounded-[var(--ds-radius-sm)]" : "text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-emphasis)] rounded-[var(--ds-radius-sm)]",
|
|
1668
|
-
dis && "opacity-disabled cursor-not-allowed hover:bg-transparent"
|
|
1669
|
-
),
|
|
1670
|
-
children: day
|
|
1671
|
-
},
|
|
1672
|
-
day
|
|
1673
|
-
);
|
|
1674
|
-
}) }, w))
|
|
1675
|
-
]
|
|
1676
|
-
}
|
|
1677
|
-
),
|
|
1678
|
-
/* @__PURE__ */ jsxs(
|
|
1679
|
-
"div",
|
|
1680
|
-
{
|
|
1681
|
-
className: "flex justify-between items-center bg-[var(--ds-bg-muted)] border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] rounded-b-[var(--ds-radius-md)]",
|
|
1682
|
-
style: { padding: "var(--ds-space-2) var(--ds-space-3)" },
|
|
1683
|
-
children: [
|
|
1684
|
-
/* @__PURE__ */ jsx(
|
|
1685
|
-
Button,
|
|
1686
|
-
{
|
|
1687
|
-
type: "button",
|
|
1688
|
-
variant: "ghost",
|
|
1689
|
-
size: "sm",
|
|
1690
|
-
onClick: () => {
|
|
1691
|
-
const now = /* @__PURE__ */ new Date();
|
|
1692
|
-
setViewDate(now);
|
|
1693
|
-
choose(now);
|
|
1694
|
-
},
|
|
1695
|
-
children: "Today"
|
|
1696
|
-
}
|
|
1697
|
-
),
|
|
1698
|
-
value && /* @__PURE__ */ jsx(
|
|
1699
|
-
Button,
|
|
1700
|
-
{
|
|
1701
|
-
type: "button",
|
|
1702
|
-
variant: "ghost",
|
|
1703
|
-
size: "sm",
|
|
1704
|
-
onClick: () => choose(null),
|
|
1705
|
-
children: "Clear"
|
|
1706
|
-
}
|
|
1707
|
-
)
|
|
1708
|
-
]
|
|
1709
|
-
}
|
|
1710
|
-
)
|
|
1711
|
-
]
|
|
1712
|
-
}
|
|
1713
|
-
),
|
|
1714
|
-
container ?? document.body
|
|
1715
|
-
)
|
|
1716
|
-
] });
|
|
1717
|
-
}
|
|
1718
|
-
var CONTROL_HEIGHT3 = {
|
|
1719
|
-
sm: "h-[var(--ds-control-height-sm)]",
|
|
1720
|
-
md: "h-[var(--ds-control-height-md)]",
|
|
1721
|
-
lg: "h-[var(--ds-control-height-lg)]"
|
|
1722
|
-
};
|
|
1723
|
-
var TEXT_SIZE3 = {
|
|
1724
|
-
sm: "text-xs",
|
|
1725
|
-
md: "text-sm",
|
|
1726
|
-
lg: "text-base"
|
|
1727
|
-
};
|
|
1728
|
-
var DEFAULT_DATE_RANGE_PRESETS = [
|
|
1729
|
-
{ label: "Today", range: () => {
|
|
1730
|
-
const t = startOfDay(/* @__PURE__ */ new Date());
|
|
1731
|
-
return { start: t, end: t };
|
|
1732
|
-
} },
|
|
1733
|
-
{ label: "Last 7 days", range: () => {
|
|
1734
|
-
const t = startOfDay(/* @__PURE__ */ new Date());
|
|
1735
|
-
return { start: addDays2(t, -6), end: t };
|
|
1736
|
-
} },
|
|
1737
|
-
{ label: "Last 30 days", range: () => {
|
|
1738
|
-
const t = startOfDay(/* @__PURE__ */ new Date());
|
|
1739
|
-
return { start: addDays2(t, -29), end: t };
|
|
1740
|
-
} },
|
|
1741
|
-
{ label: "This month", range: () => {
|
|
1742
|
-
const t = /* @__PURE__ */ new Date();
|
|
1743
|
-
return { start: new Date(t.getFullYear(), t.getMonth(), 1), end: startOfDay(t) };
|
|
1744
|
-
} },
|
|
1745
|
-
{ label: "Last month", range: () => {
|
|
1746
|
-
const t = /* @__PURE__ */ new Date();
|
|
1747
|
-
return { start: new Date(t.getFullYear(), t.getMonth() - 1, 1), end: new Date(t.getFullYear(), t.getMonth(), 0) };
|
|
1748
|
-
} }
|
|
1749
|
-
];
|
|
1750
|
-
function DateRangePicker({
|
|
1751
|
-
value,
|
|
1752
|
-
onChange: onChangeProp,
|
|
1753
|
-
placeholder = "Pick a date range",
|
|
1754
|
-
disabled,
|
|
1755
|
-
error = false,
|
|
1756
|
-
label,
|
|
1757
|
-
id,
|
|
1758
|
-
className,
|
|
1759
|
-
ref,
|
|
1760
|
-
container,
|
|
1761
|
-
min,
|
|
1762
|
-
max,
|
|
1763
|
-
presets = DEFAULT_DATE_RANGE_PRESETS,
|
|
1764
|
-
weekStartsOn: weekStartsOnProp,
|
|
1765
|
-
size: sizeProp,
|
|
1766
|
-
...wiring
|
|
1767
|
-
}) {
|
|
1768
|
-
const weekStartsOn = useWeekStart(weekStartsOnProp);
|
|
1769
|
-
const { weekdayNames, formatDayLong, formatDayMedium, formatDayRange, formatMonthRange, formatMonthYear } = useDateWords();
|
|
1770
|
-
const hydrated = useHydrated();
|
|
1771
|
-
const now = useToday();
|
|
1772
|
-
const onChange = useReportedChange(onChangeProp, value);
|
|
1773
|
-
const contextSize = useContext(ControlSizeContext);
|
|
1774
|
-
const size = sizeProp ?? contextSize ?? "md";
|
|
1775
|
-
const [open, setOpen] = useState(false);
|
|
1776
|
-
const [viewDate, setViewDate] = useState(() => value.start ?? /* @__PURE__ */ new Date());
|
|
1777
|
-
const [hover, setHover] = useState(null);
|
|
1778
|
-
const triggerRef = useRef(null);
|
|
1779
|
-
const panelRef = useRef(null);
|
|
1780
|
-
const generatedId = useId();
|
|
1781
|
-
const control = useFieldControl({ ...wiring, id, error: error || void 0 }, { requiredInDescription: true });
|
|
1782
|
-
useInputModality();
|
|
1783
|
-
const triggerId = control.id ?? generatedId;
|
|
1784
|
-
const labelledBy = control.labelId ? `${control.labelId} ${triggerId}` : void 0;
|
|
695
|
+
}, [open, isPhone]);
|
|
1785
696
|
const pos = usePosition(triggerRef, panelRef, open, { side: "bottom", align: "start", offset: 4, flip: true });
|
|
697
|
+
const invalid = control.invalid || typedInvalid;
|
|
1786
698
|
const today = now && startOfDay(now);
|
|
1787
699
|
const dayNames = weekdayNames(weekStartsOn, "narrow");
|
|
1788
700
|
const dayNamesLong = weekdayNames(weekStartsOn, "long");
|
|
@@ -1799,8 +711,8 @@ function DateRangePicker({
|
|
|
1799
711
|
}
|
|
1800
712
|
const showDay = (d) => {
|
|
1801
713
|
setFocusDate(d);
|
|
1802
|
-
const
|
|
1803
|
-
const offset =
|
|
714
|
+
const monthIndex = (x) => x.getFullYear() * 12 + x.getMonth();
|
|
715
|
+
const offset = monthIndex(d) - monthIndex(viewDate);
|
|
1804
716
|
if (offset < 0) setViewDate(new Date(d.getFullYear(), d.getMonth(), 1));
|
|
1805
717
|
else if (offset > 1) setViewDate(new Date(d.getFullYear(), d.getMonth() - 1, 1));
|
|
1806
718
|
};
|
|
@@ -1815,7 +727,7 @@ function DateRangePicker({
|
|
|
1815
727
|
setViewDate(addMonths(viewDate, n));
|
|
1816
728
|
setFocusDate(addMonthsClamped(focusDate, n));
|
|
1817
729
|
};
|
|
1818
|
-
const { isTop: isTopLayer, returnFocus } = usePopupFocus(open, { trigger:
|
|
730
|
+
const { isTop: isTopLayer, returnFocus } = usePopupFocus(open, { trigger: buttonRef, panel: panelRef, close: () => setOpen(false), tabExits: "edges" });
|
|
1819
731
|
const focusActiveDay = useLatest(grid.focusActive);
|
|
1820
732
|
useEffect(() => {
|
|
1821
733
|
if (!open) return;
|
|
@@ -1842,7 +754,20 @@ function DateRangePicker({
|
|
|
1842
754
|
document.removeEventListener("keydown", onKey);
|
|
1843
755
|
};
|
|
1844
756
|
}, [open, isTopLayer, returnFocus]);
|
|
1845
|
-
const isDisabledDay = (d) => min && d < startOfDay(min) || max && d > startOfDay(max) ||
|
|
757
|
+
const isDisabledDay = (d) => min && d < startOfDay(min) || max && d > startOfDay(max) || isExcludedDay(disabledDates, d);
|
|
758
|
+
const takeTyped = ([s, e], [fs, fe]) => {
|
|
759
|
+
const refused = (d, filled) => filled && (!d || isDisabledDay(d));
|
|
760
|
+
const start = fs ? s : value.start;
|
|
761
|
+
const end = fe ? e : value.end;
|
|
762
|
+
const bad = refused(s, fs) || refused(e, fe) || !!start && !!end && end < start;
|
|
763
|
+
setTypedInvalid(bad);
|
|
764
|
+
if (bad) return;
|
|
765
|
+
const same = (a, b) => a && b ? isSameDay(a, b) : a === b;
|
|
766
|
+
if (!same(start, value.start) || !same(end, value.end)) {
|
|
767
|
+
onChange({ start, end });
|
|
768
|
+
if (start) setViewDate(start);
|
|
769
|
+
}
|
|
770
|
+
};
|
|
1846
771
|
const selectDay = (d) => {
|
|
1847
772
|
if (isDisabledDay(d)) return;
|
|
1848
773
|
if (!value.start || value.start && value.end) {
|
|
@@ -1861,44 +786,70 @@ function DateRangePicker({
|
|
|
1861
786
|
const rangeStart = value.start;
|
|
1862
787
|
const rangeEnd2 = value.end ?? previewEnd;
|
|
1863
788
|
const inRange = (d) => !!(rangeStart && rangeEnd2 && d > rangeStart && d < rangeEnd2);
|
|
1864
|
-
const months = [viewDate, addMonths(viewDate, 1)];
|
|
789
|
+
const months = isPhone ? [viewDate] : [viewDate, addMonths(viewDate, 1)];
|
|
1865
790
|
const summary = !hydrated ? null : value.start && value.end ? formatDayRange(value.start, value.end) : value.start ? `${formatDayMedium(value.start)} \u2013 \u2026` : null;
|
|
1866
|
-
const pendingValue = !hydrated && !!value.start;
|
|
1867
791
|
return /* @__PURE__ */ jsxs("div", { ref, className: cn(className), children: [
|
|
1868
792
|
label && /* @__PURE__ */ jsx("label", { htmlFor: triggerId, className: "block text-sm font-medium text-[var(--ds-text-primary)] mb-ds-1", children: label }),
|
|
1869
793
|
control.requiredNote,
|
|
1870
794
|
/* @__PURE__ */ jsxs(
|
|
1871
|
-
"
|
|
795
|
+
"div",
|
|
1872
796
|
{
|
|
1873
|
-
id: triggerId,
|
|
1874
797
|
ref: triggerRef,
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
"aria-
|
|
798
|
+
"data-date-range-field": "",
|
|
799
|
+
role: "group",
|
|
800
|
+
id: triggerId,
|
|
801
|
+
"aria-label": control.labelId ? void 0 : label ?? control.label ?? "Dates",
|
|
802
|
+
"aria-labelledby": control.labelId,
|
|
1879
803
|
"aria-describedby": control.describedBy,
|
|
1880
|
-
"aria-
|
|
1881
|
-
"aria-
|
|
1882
|
-
"aria-expanded": open,
|
|
804
|
+
"aria-description": !value.start && !value.end ? placeholder : void 0,
|
|
805
|
+
"aria-invalid": invalid || void 0,
|
|
1883
806
|
className: cn(
|
|
1884
807
|
"flex items-center gap-ds-2 w-full",
|
|
1885
|
-
|
|
1886
|
-
|
|
808
|
+
CONTROL_HEIGHT2[size],
|
|
809
|
+
TEXT_SIZE2[size],
|
|
1887
810
|
"border-[length:var(--ds-border-width)]",
|
|
1888
|
-
|
|
811
|
+
invalid ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
|
|
1889
812
|
"bg-[var(--ds-input-bg)] rounded-[var(--ds-radius-md)]",
|
|
1890
813
|
"shadow-[var(--ds-input-shadow)]",
|
|
1891
|
-
"transition-colors
|
|
814
|
+
"transition-colors",
|
|
1892
815
|
"px-ds-3 py-ds-2",
|
|
1893
|
-
!
|
|
1894
|
-
open && (
|
|
1895
|
-
|
|
816
|
+
!invalid && !disabled && !open && "hover:border-[var(--ds-input-border-hover)]",
|
|
817
|
+
open && (invalid ? ERROR_ACTIVE_RING : ACTIVE_RING),
|
|
818
|
+
// the parts mark which has focus (their tint); the field draws the focus, as DatePicker's does
|
|
819
|
+
invalid ? ERROR_FOCUS_WITHIN_RING : FIELD_FOCUS_WITHIN_RING,
|
|
1896
820
|
disabled && "opacity-disabled cursor-not-allowed",
|
|
1897
|
-
|
|
821
|
+
"text-[var(--ds-text-primary)]"
|
|
1898
822
|
),
|
|
1899
823
|
children: [
|
|
1900
|
-
/* @__PURE__ */ jsx(Icon, { name: "calendar", size: 14, className: "text-[var(--ds-text-muted)]" }),
|
|
1901
|
-
/* @__PURE__ */ jsx("
|
|
824
|
+
/* @__PURE__ */ jsx(Icon, { name: "calendar", size: 14, className: "text-[var(--ds-text-muted)] shrink-0" }),
|
|
825
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center min-w-0 flex-1 tabular-nums overflow-hidden", onClick: () => focusPart.current(0), children: /* @__PURE__ */ jsx(
|
|
826
|
+
DateSegmentFields,
|
|
827
|
+
{
|
|
828
|
+
values: [value.start, value.end],
|
|
829
|
+
names: ["Start", "End"],
|
|
830
|
+
dayFirst,
|
|
831
|
+
hydrated,
|
|
832
|
+
disabled,
|
|
833
|
+
focusRef: (focus) => {
|
|
834
|
+
focusPart.current = focus;
|
|
835
|
+
},
|
|
836
|
+
onChange: takeTyped
|
|
837
|
+
}
|
|
838
|
+
) }),
|
|
839
|
+
/* @__PURE__ */ jsx(AutoTooltip, { content: "Choose a date range", children: /* @__PURE__ */ jsx(
|
|
840
|
+
"button",
|
|
841
|
+
{
|
|
842
|
+
ref: buttonRef,
|
|
843
|
+
type: "button",
|
|
844
|
+
"aria-label": "Choose a date range",
|
|
845
|
+
"aria-haspopup": "dialog",
|
|
846
|
+
"aria-expanded": open,
|
|
847
|
+
onClick: () => !disabled && setOpen((o) => !o),
|
|
848
|
+
disabled,
|
|
849
|
+
className: cn("shrink-0 -mr-ds-1 rounded-[var(--ds-radius-sm)] text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] disabled:cursor-not-allowed", FOCUS_RING),
|
|
850
|
+
children: /* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: 14 })
|
|
851
|
+
}
|
|
852
|
+
) })
|
|
1902
853
|
]
|
|
1903
854
|
}
|
|
1904
855
|
),
|
|
@@ -1912,6 +863,9 @@ function DateRangePicker({
|
|
|
1912
863
|
tabIndex: -1,
|
|
1913
864
|
className: cn(
|
|
1914
865
|
"fixed z-[var(--ds-z-popover)] flex outline-none",
|
|
866
|
+
// on a phone the panel stays inside the screen: its quick ranges above the month, the month scrolling under
|
|
867
|
+
// them if it must, and its footer, with Clear, always in view (item 35)
|
|
868
|
+
isPhone && "flex-col max-w-[calc(100vw-16px)] max-h-[calc(100dvh-16px)]",
|
|
1915
869
|
"bg-[var(--ds-bg-surface-elevated)]",
|
|
1916
870
|
"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]",
|
|
1917
871
|
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
@@ -1920,57 +874,73 @@ function DateRangePicker({
|
|
|
1920
874
|
),
|
|
1921
875
|
style: { top: pos.top, left: pos.left },
|
|
1922
876
|
children: [
|
|
1923
|
-
presets.length > 0 && /* @__PURE__ */ jsx(
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
877
|
+
presets.length > 0 && /* @__PURE__ */ jsx(
|
|
878
|
+
"div",
|
|
879
|
+
{
|
|
880
|
+
"data-range-presets": "",
|
|
881
|
+
ref: isPhone ? presetEdges.ref : void 0,
|
|
882
|
+
...isPhone ? presetEdges.fadeProps : {},
|
|
883
|
+
className: cn(
|
|
884
|
+
"border-[var(--ds-border-subtle)]",
|
|
885
|
+
isPhone ? "flex flex-nowrap gap-ds-1.5 overflow-x-auto px-ds-3 py-ds-2.5 scroll-p-[4px] border-b-[length:var(--ds-border-width)] shrink-0 [scrollbar-width:none]" : "p-ds-2 flex flex-col gap-ds-0.5 border-r-[length:var(--ds-border-width)] min-w-[140px]"
|
|
886
|
+
),
|
|
887
|
+
children: presets.map((p) => /* @__PURE__ */ jsx(Button, { type: "button", variant: isPhone ? "secondary" : "ghost", size: "sm", className: isPhone ? "shrink-0 whitespace-nowrap rounded-[var(--ds-radius-full)]" : "justify-start", onClick: () => {
|
|
888
|
+
const r = p.range();
|
|
889
|
+
returnFocus();
|
|
890
|
+
onChange(r);
|
|
891
|
+
setViewDate(r.start ?? /* @__PURE__ */ new Date());
|
|
892
|
+
setOpen(false);
|
|
893
|
+
}, children: p.label }, p.label))
|
|
894
|
+
}
|
|
895
|
+
),
|
|
896
|
+
/* @__PURE__ */ jsxs("div", { className: cn("flex flex-col", isPhone && "min-h-0"), children: [
|
|
897
|
+
/* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between bg-[var(--ds-bg-muted)] px-ds-3 py-ds-2 shrink-0", !isPhone && "rounded-tr-[var(--ds-radius-md)]"), children: [
|
|
1932
898
|
/* @__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" }) }),
|
|
1933
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-[var(--ds-text-primary)]", children: formatMonthRange(months[0], months[1]) }),
|
|
1934
|
-
/* @__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 }) })
|
|
1935
|
-
] }),
|
|
1936
|
-
/* @__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) =>
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
899
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-[var(--ds-text-primary)]", children: months[1] ? formatMonthRange(months[0], months[1]) : formatMonthYear(months[0]) }),
|
|
900
|
+
/* @__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 }) })
|
|
901
|
+
] }),
|
|
902
|
+
/* @__PURE__ */ jsx("div", { ref: gridRef, onKeyDown: grid.onKeyDown, className: cn("flex gap-ds-4 px-ds-3 py-ds-2", isPhone && "min-h-0 overflow-y-auto"), onMouseLeave: () => setHover(null), children: months.map((m) => (
|
|
903
|
+
// on a phone the one month fills the panel, its days a comfortable tap (the look check's second round)
|
|
904
|
+
/* @__PURE__ */ jsxs("div", { role: "grid", "aria-label": formatMonthYear(m), className: cn(isPhone ? "w-full" : "w-[224px]", "flex flex-col gap-[4px]"), children: [
|
|
905
|
+
/* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 gap-[4px] 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)) }),
|
|
906
|
+
getMonthGrid(m.getFullYear(), m.getMonth(), weekStartsOn).map((week, w) => /* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 gap-[4px]", children: week.map((d) => {
|
|
907
|
+
if (!isSameMonth(d, m)) return /* @__PURE__ */ jsx("div", { role: "gridcell" }, d.toISOString());
|
|
908
|
+
const isStart = !!rangeStart && isSameDay(d, rangeStart);
|
|
909
|
+
const isEnd = !!rangeEnd2 && isSameDay(d, rangeEnd2);
|
|
910
|
+
const between = inRange(d);
|
|
911
|
+
const dis = isDisabledDay(d);
|
|
912
|
+
return /* @__PURE__ */ jsx(
|
|
913
|
+
"button",
|
|
914
|
+
{
|
|
915
|
+
type: "button",
|
|
916
|
+
role: "gridcell",
|
|
917
|
+
"data-grid-key": dayKey(d),
|
|
918
|
+
tabIndex: grid.tabIndexOf(d),
|
|
919
|
+
"aria-disabled": dis || void 0,
|
|
920
|
+
onClick: () => selectDay(d),
|
|
921
|
+
onFocus: () => {
|
|
922
|
+
if (!isSameDay(d, focusDate)) setFocusDate(d);
|
|
923
|
+
},
|
|
924
|
+
onMouseEnter: () => setHover(d),
|
|
925
|
+
"aria-selected": isStart || isEnd || between,
|
|
926
|
+
"aria-current": today !== null && isSameDay(d, today) ? "date" : void 0,
|
|
927
|
+
"aria-label": formatDayLong(d),
|
|
928
|
+
className: cn(
|
|
929
|
+
"w-full aspect-square flex items-center justify-center",
|
|
930
|
+
isPhone ? "text-sm" : "text-xs",
|
|
931
|
+
"transition-colors cursor-pointer",
|
|
932
|
+
FOCUS_RING,
|
|
933
|
+
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-ink)] text-[var(--ds-accent-ink)] font-medium rounded-[var(--ds-radius-sm)]" : "text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-emphasis)] rounded-[var(--ds-radius-sm)]",
|
|
934
|
+
dis && "opacity-disabled cursor-not-allowed hover:bg-transparent"
|
|
935
|
+
),
|
|
936
|
+
children: d.getDate()
|
|
1955
937
|
},
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
"transition-colors cursor-pointer",
|
|
1963
|
-
FOCUS_RING,
|
|
1964
|
-
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-ink)] text-[var(--ds-accent-ink)] font-medium rounded-[var(--ds-radius-sm)]" : "text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-emphasis)] rounded-[var(--ds-radius-sm)]",
|
|
1965
|
-
dis && "opacity-disabled cursor-not-allowed hover:bg-transparent"
|
|
1966
|
-
),
|
|
1967
|
-
children: d.getDate()
|
|
1968
|
-
},
|
|
1969
|
-
d.toISOString()
|
|
1970
|
-
);
|
|
1971
|
-
}) }, w))
|
|
1972
|
-
] }, `${m.getFullYear()}-${m.getMonth()}`)) }),
|
|
1973
|
-
/* @__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: [
|
|
938
|
+
d.toISOString()
|
|
939
|
+
);
|
|
940
|
+
}) }, w))
|
|
941
|
+
] }, `${m.getFullYear()}-${m.getMonth()}`)
|
|
942
|
+
)) }),
|
|
943
|
+
/* @__PURE__ */ jsxs("div", { className: cn("flex justify-between items-center bg-[var(--ds-bg-muted)] border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] px-ds-3 py-ds-2 shrink-0", isPhone ? "rounded-b-[var(--ds-radius-md)]" : "rounded-br-[var(--ds-radius-md)]"), children: [
|
|
1974
944
|
/* @__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" }),
|
|
1975
945
|
(value.start || value.end) && /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => {
|
|
1976
946
|
onChange({ start: null, end: null });
|
|
@@ -2103,10 +1073,10 @@ var atDay = (year, month, day, time) => new Date(year, month, day, time.getHours
|
|
|
2103
1073
|
var dayIndex = (d) => Math.round(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()) / 864e5);
|
|
2104
1074
|
var isMidnight = (d) => d.getHours() === 0 && d.getMinutes() === 0 && d.getSeconds() === 0 && d.getMilliseconds() === 0;
|
|
2105
1075
|
function nthWeekdayOf(year, month, week, weekday2) {
|
|
2106
|
-
const
|
|
2107
|
-
if (week === -1) return
|
|
1076
|
+
const last = daysIn(year, month);
|
|
1077
|
+
if (week === -1) return last - (new Date(year, month, last).getDay() - weekday2 + 7) % 7;
|
|
2108
1078
|
const day = 1 + (weekday2 - new Date(year, month, 1).getDay() + 7) % 7 + (week - 1) * 7;
|
|
2109
|
-
return day <=
|
|
1079
|
+
return day <= last ? day : null;
|
|
2110
1080
|
}
|
|
2111
1081
|
function nthOf(date) {
|
|
2112
1082
|
const d = date.getDate();
|
|
@@ -2179,8 +1149,8 @@ function occurrenceAt(event, start) {
|
|
|
2179
1149
|
}
|
|
2180
1150
|
function stopOf(event) {
|
|
2181
1151
|
if (event.allDay) {
|
|
2182
|
-
const
|
|
2183
|
-
return new Date(
|
|
1152
|
+
const last = event.end ?? event.start;
|
|
1153
|
+
return new Date(last.getFullYear(), last.getMonth(), last.getDate() + 1);
|
|
2184
1154
|
}
|
|
2185
1155
|
return event.end ?? new Date(event.start.getTime() + 36e5);
|
|
2186
1156
|
}
|
|
@@ -2746,8 +1716,8 @@ var sizeClasses = {
|
|
|
2746
1716
|
full: "max-w-[calc(100vw-2rem)]"
|
|
2747
1717
|
};
|
|
2748
1718
|
function Dialog({ open, onClose: onCloseProp, title, description, children, footer, variant = "default", size = "md", alert = false, container, onSubmit, dirty, onDiscard }) {
|
|
2749
|
-
const { marked, mark } = useOverlayMark(open);
|
|
2750
|
-
const guard = useDirtyGuard(dirty ?? marked, onCloseProp, onDiscard);
|
|
1719
|
+
const { marked, pending, mark } = useOverlayMark(open);
|
|
1720
|
+
const guard = useDirtyGuard((dirty ?? marked) || pending, onCloseProp, onDiscard);
|
|
2751
1721
|
const onClose = guard.requestClose;
|
|
2752
1722
|
const titleId = useId();
|
|
2753
1723
|
const descriptionId = useId();
|
|
@@ -2756,7 +1726,13 @@ function Dialog({ open, onClose: onCloseProp, title, description, children, foot
|
|
|
2756
1726
|
const dialogRef = useRef(null);
|
|
2757
1727
|
const opener = useRef(null);
|
|
2758
1728
|
const defaultButtonRef = useRef(null);
|
|
2759
|
-
const
|
|
1729
|
+
const bodyInset = useScrollbarInset();
|
|
1730
|
+
const [bodyEl, setBodyEl] = useState(null);
|
|
1731
|
+
const bodyRef = useCallback((el) => {
|
|
1732
|
+
bodyInset(el);
|
|
1733
|
+
setBodyEl(el);
|
|
1734
|
+
}, [bodyInset]);
|
|
1735
|
+
useKeyboardScroll(bodyEl, title, open);
|
|
2760
1736
|
const onCloseRef = useLatest(onClose);
|
|
2761
1737
|
const onSubmitRef = useLatest(onSubmit);
|
|
2762
1738
|
const isTopLayer = useOverlayLayer(open);
|
|
@@ -2764,8 +1740,7 @@ function Dialog({ open, onClose: onCloseProp, title, description, children, foot
|
|
|
2764
1740
|
const before = useFocusBeforeOpen(open);
|
|
2765
1741
|
useEffect(() => {
|
|
2766
1742
|
if (!open) return;
|
|
2767
|
-
|
|
2768
|
-
opener.current = active instanceof HTMLElement && active !== document.body && active.isConnected ? rememberFocus(active) : null;
|
|
1743
|
+
opener.current = rememberOpener(before.current, dialogRef.current);
|
|
2769
1744
|
}, [open, before]);
|
|
2770
1745
|
useEffect(() => {
|
|
2771
1746
|
if (!open) return;
|
|
@@ -2880,7 +1855,7 @@ function Dialog({ open, onClose: onCloseProp, title, description, children, foot
|
|
|
2880
1855
|
),
|
|
2881
1856
|
description && /* @__PURE__ */ jsx("p", { id: descriptionId, className: "mt-ds-2 text-sm text-[var(--ds-text-muted)]", children: description })
|
|
2882
1857
|
] }),
|
|
2883
|
-
/* @__PURE__ */ jsx(
|
|
1858
|
+
/* @__PURE__ */ jsx(AutoTooltip, { content: "Close", children: /* @__PURE__ */ jsx(
|
|
2884
1859
|
"button",
|
|
2885
1860
|
{
|
|
2886
1861
|
type: "button",
|
|
@@ -2890,13 +1865,13 @@ function Dialog({ open, onClose: onCloseProp, title, description, children, foot
|
|
|
2890
1865
|
"aria-label": "Close",
|
|
2891
1866
|
children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 18 })
|
|
2892
1867
|
}
|
|
2893
|
-
)
|
|
1868
|
+
) })
|
|
2894
1869
|
] }),
|
|
2895
1870
|
children && /* @__PURE__ */ jsx(
|
|
2896
1871
|
"div",
|
|
2897
1872
|
{
|
|
2898
1873
|
ref: bodyRef,
|
|
2899
|
-
className: "min-h-0 flex-[0_1_auto] overflow-y-auto pb-ds-6",
|
|
1874
|
+
className: cn("min-h-0 flex-[0_1_auto] overflow-y-auto pb-ds-6", FOCUS_INSET),
|
|
2900
1875
|
style: {
|
|
2901
1876
|
paddingLeft: variant === "destructive" ? "calc(var(--ds-page-gutter) + 2.5rem + var(--ds-space-3))" : "var(--ds-page-gutter)",
|
|
2902
1877
|
paddingRight: insetLessScrollbar("var(--ds-page-gutter)")
|
|
@@ -3112,7 +2087,7 @@ var running = (item) => item.status === "queued" || item.status === "uploading";
|
|
|
3112
2087
|
var failureOf = (err) => err instanceof Error && err.message ? err.message : "The upload didn't work.";
|
|
3113
2088
|
var percentOf = (value) => typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.min(100, value)) : 0;
|
|
3114
2089
|
var STILL_UPLOADING = "Wait for your files to finish uploading";
|
|
3115
|
-
function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accept, multiple = true, maxSize, className, error = false, label, id }) {
|
|
2090
|
+
function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accept, multiple = true, maxSize, className, error = false, label, id, "aria-label": ariaLabel }) {
|
|
3116
2091
|
const controlled = files !== void 0;
|
|
3117
2092
|
const [own, setOwn] = useState([]);
|
|
3118
2093
|
const shown = controlled ? files : own;
|
|
@@ -3248,10 +2223,10 @@ function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accep
|
|
|
3248
2223
|
focusAfterRemoval(rows, gone.index, inputRef.current);
|
|
3249
2224
|
return;
|
|
3250
2225
|
}
|
|
3251
|
-
const
|
|
2226
|
+
const last = lastAction.current;
|
|
3252
2227
|
const active = document.activeElement;
|
|
3253
|
-
if (!
|
|
3254
|
-
const row = Array.from(listRef.current?.querySelectorAll(":scope > li") ?? []).find((li) => li.dataset.uploadId ===
|
|
2228
|
+
if (!last || last.el.isConnected || active && active !== document.body) return;
|
|
2229
|
+
const row = Array.from(listRef.current?.querySelectorAll(":scope > li") ?? []).find((li) => li.dataset.uploadId === last.id);
|
|
3255
2230
|
row?.querySelector("button")?.focus();
|
|
3256
2231
|
}, [shown]);
|
|
3257
2232
|
const addFiles = useCallback(
|
|
@@ -3343,6 +2318,7 @@ function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accep
|
|
|
3343
2318
|
accept,
|
|
3344
2319
|
multiple,
|
|
3345
2320
|
className: "sr-only",
|
|
2321
|
+
"aria-label": field ? void 0 : ariaLabel,
|
|
3346
2322
|
"aria-labelledby": field ? field.labelId : void 0,
|
|
3347
2323
|
"aria-describedby": describedBy,
|
|
3348
2324
|
"aria-invalid": invalid || void 0,
|
|
@@ -3566,12 +2542,12 @@ function fromValue(v, use24Hour) {
|
|
|
3566
2542
|
const h24 = Number(m[1]);
|
|
3567
2543
|
return use24Hour ? { hour: h24, minute: Number(m[2]), period: null } : { hour: h24 % 12 === 0 ? 12 : h24 % 12, minute: Number(m[2]), period: h24 >= 12 ? "PM" : "AM" };
|
|
3568
2544
|
}
|
|
3569
|
-
var
|
|
2545
|
+
var CONTROL_HEIGHT3 = {
|
|
3570
2546
|
sm: "h-[var(--ds-control-height-sm)]",
|
|
3571
2547
|
md: "h-[var(--ds-control-height-md)]",
|
|
3572
2548
|
lg: "h-[var(--ds-control-height-lg)]"
|
|
3573
2549
|
};
|
|
3574
|
-
var
|
|
2550
|
+
var TEXT_SIZE3 = {
|
|
3575
2551
|
sm: "text-xs",
|
|
3576
2552
|
md: "text-sm",
|
|
3577
2553
|
lg: "text-base"
|
|
@@ -3664,7 +2640,7 @@ function TimePicker({
|
|
|
3664
2640
|
if (!open) return;
|
|
3665
2641
|
const id2 = requestAnimationFrame(() => {
|
|
3666
2642
|
const panel = panelRef.current;
|
|
3667
|
-
(panel?.querySelector('[
|
|
2643
|
+
(panel?.querySelector('[aria-selected="true"]') ?? panel?.querySelector("button"))?.focus();
|
|
3668
2644
|
});
|
|
3669
2645
|
return () => cancelAnimationFrame(id2);
|
|
3670
2646
|
}, [open]);
|
|
@@ -3680,7 +2656,7 @@ function TimePicker({
|
|
|
3680
2656
|
const columns2 = Array.from(panelRef.current?.querySelectorAll("[data-column]") ?? []);
|
|
3681
2657
|
const idx = columns2.indexOf(column);
|
|
3682
2658
|
const target = columns2[idx + (e.key === "ArrowRight" ? 1 : -1)];
|
|
3683
|
-
next = target?.querySelector('[
|
|
2659
|
+
next = target?.querySelector('[aria-selected="true"]') ?? target?.querySelector("button") ?? null;
|
|
3684
2660
|
} else return;
|
|
3685
2661
|
if (next instanceof HTMLElement) {
|
|
3686
2662
|
e.preventDefault();
|
|
@@ -3804,17 +2780,34 @@ function TimePicker({
|
|
|
3804
2780
|
return;
|
|
3805
2781
|
}
|
|
3806
2782
|
if (/^\d$/.test(key)) {
|
|
3807
|
-
|
|
3808
|
-
setBuffers((b) => ({ ...b, [k]: r.advance ? "" : r.buffer }));
|
|
3809
|
-
setSegment(k, r.value);
|
|
3810
|
-
if (r.advance) focusSegment(index + 1);
|
|
2783
|
+
typeInto(index, key);
|
|
3811
2784
|
return;
|
|
3812
2785
|
}
|
|
3813
2786
|
if (!use24Hour && /^[aApP]$/.test(key)) {
|
|
3814
2787
|
setSegment("period", /^[aA]$/.test(key) ? "AM" : "PM");
|
|
3815
2788
|
return;
|
|
3816
2789
|
}
|
|
2790
|
+
if (separatorMovesOn(TIME_SEPARATORS, key, !!buffers[k] || segs[k] !== null)) focusSegment(index + 1);
|
|
3817
2791
|
};
|
|
2792
|
+
const typeInto = (index, digit) => {
|
|
2793
|
+
const spec = specs[index];
|
|
2794
|
+
const k = spec.key;
|
|
2795
|
+
const r = typeDigit(spec, buffers[k] ?? "", digit);
|
|
2796
|
+
if (r.kind === "here") {
|
|
2797
|
+
setBuffers((b) => ({ ...b, [k]: r.buffer }));
|
|
2798
|
+
setSegment(k, r.value);
|
|
2799
|
+
return;
|
|
2800
|
+
}
|
|
2801
|
+
const nextSpec = specs[index + 1];
|
|
2802
|
+
if (!nextSpec) return;
|
|
2803
|
+
focusSegment(index + 1);
|
|
2804
|
+
const carried = typeDigit(nextSpec, "", digit);
|
|
2805
|
+
if (carried.kind !== "here") return;
|
|
2806
|
+
const nk = nextSpec.key;
|
|
2807
|
+
setBuffers((b) => ({ ...b, [nk]: carried.buffer }));
|
|
2808
|
+
setSegment(nk, carried.value);
|
|
2809
|
+
};
|
|
2810
|
+
const freshSegment = (k) => setBuffers((b) => b[k] ? { ...b, [k]: "" } : b);
|
|
3818
2811
|
const shown = (k, spec) => {
|
|
3819
2812
|
const b = buffers[k];
|
|
3820
2813
|
if (b && segs[k] === null) return b;
|
|
@@ -3829,7 +2822,7 @@ function TimePicker({
|
|
|
3829
2822
|
"data-time-field": "",
|
|
3830
2823
|
role: "group",
|
|
3831
2824
|
id: control.id,
|
|
3832
|
-
"aria-label": control.labelId ? void 0 : "Time",
|
|
2825
|
+
"aria-label": control.labelId ? void 0 : control.label ?? "Time",
|
|
3833
2826
|
"aria-labelledby": control.labelId,
|
|
3834
2827
|
"aria-describedby": control.describedBy,
|
|
3835
2828
|
"aria-invalid": control.invalid || void 0,
|
|
@@ -3842,8 +2835,8 @@ function TimePicker({
|
|
|
3842
2835
|
},
|
|
3843
2836
|
className: cn(
|
|
3844
2837
|
"flex w-full items-center gap-ds-2",
|
|
3845
|
-
|
|
3846
|
-
|
|
2838
|
+
CONTROL_HEIGHT3[size],
|
|
2839
|
+
TEXT_SIZE3[size],
|
|
3847
2840
|
"border-[length:var(--ds-border-width)]",
|
|
3848
2841
|
control.invalid ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
|
|
3849
2842
|
"bg-[var(--ds-input-bg)] rounded-[var(--ds-radius-md)]",
|
|
@@ -3879,6 +2872,8 @@ function TimePicker({
|
|
|
3879
2872
|
"aria-valuenow": segs[k] ?? void 0,
|
|
3880
2873
|
"aria-valuetext": segs[k] === null ? "empty" : pad2(segs[k]),
|
|
3881
2874
|
onKeyDown: (e) => onSegmentKeyDown(e, i, spec),
|
|
2875
|
+
onFocus: () => freshSegment(k),
|
|
2876
|
+
onMouseDown: () => freshSegment(k),
|
|
3882
2877
|
onClick: (e) => e.stopPropagation(),
|
|
3883
2878
|
className: cn("rounded-[var(--ds-radius-sm)] px-[2px] outline-none focus:bg-[var(--ds-accent-subtle)] focus:text-[var(--ds-accent-ink)] cursor-text", segs[k] === null && !buffers[k] && "text-[var(--ds-text-muted)]"),
|
|
3884
2879
|
children: shown(k, spec)
|
|
@@ -3907,7 +2902,7 @@ function TimePicker({
|
|
|
3907
2902
|
}
|
|
3908
2903
|
)
|
|
3909
2904
|
] }),
|
|
3910
|
-
/* @__PURE__ */ jsx(
|
|
2905
|
+
/* @__PURE__ */ jsx(AutoTooltip, { content: "Choose a time", children: /* @__PURE__ */ jsx(
|
|
3911
2906
|
"button",
|
|
3912
2907
|
{
|
|
3913
2908
|
ref: buttonRef,
|
|
@@ -3921,7 +2916,7 @@ function TimePicker({
|
|
|
3921
2916
|
className: cn("shrink-0 -mr-ds-1 rounded-[var(--ds-radius-sm)] text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] disabled:cursor-not-allowed", FOCUS_RING),
|
|
3922
2917
|
children: /* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: 14 })
|
|
3923
2918
|
}
|
|
3924
|
-
)
|
|
2919
|
+
) })
|
|
3925
2920
|
]
|
|
3926
2921
|
}
|
|
3927
2922
|
),
|
|
@@ -3944,13 +2939,14 @@ function TimePicker({
|
|
|
3944
2939
|
),
|
|
3945
2940
|
style: { top: pos.top, left: pos.left },
|
|
3946
2941
|
children: /* @__PURE__ */ jsxs("div", { ref: setColumns, className: "inline-flex p-ds-1 gap-ds-1 tabular-nums", children: [
|
|
3947
|
-
/* @__PURE__ */ jsx("div", { "data-column": true, className: "flex max-h-48 w-[calc(var(--ds-space-10)+8px)] flex-col gap-[4px] overflow-y-auto p-[4px] scroll-p-[4px]", children: hours.map((h, i) => /* @__PURE__ */ jsx(
|
|
2942
|
+
/* @__PURE__ */ jsx("div", { "data-column": true, role: "listbox", "aria-label": "Hours", className: "flex max-h-48 w-[calc(var(--ds-space-10)+8px)] flex-col gap-[4px] overflow-y-auto p-[4px] scroll-p-[4px]", children: hours.map((h, i) => /* @__PURE__ */ jsx(
|
|
3948
2943
|
"button",
|
|
3949
2944
|
{
|
|
3950
2945
|
type: "button",
|
|
2946
|
+
role: "option",
|
|
3951
2947
|
tabIndex: i === stopOf2("hour", chosenHour) ? 0 : -1,
|
|
3952
2948
|
onFocus: () => holdStop("hour", i),
|
|
3953
|
-
"
|
|
2949
|
+
"aria-selected": use24Hour ? h === parseInt(value) : h === parsed.hour,
|
|
3954
2950
|
onMouseDown: (e) => e.preventDefault(),
|
|
3955
2951
|
onClick: () => emitChange(h, parsed.minute, parsed.period),
|
|
3956
2952
|
className: cn(
|
|
@@ -3964,13 +2960,14 @@ function TimePicker({
|
|
|
3964
2960
|
h
|
|
3965
2961
|
)) }),
|
|
3966
2962
|
/* @__PURE__ */ jsx("div", { className: "w-px bg-[var(--ds-border-subtle)]" }),
|
|
3967
|
-
/* @__PURE__ */ jsx("div", { "data-column": true, className: "flex max-h-48 w-[calc(var(--ds-space-10)+8px)] flex-col gap-[4px] overflow-y-auto p-[4px] scroll-p-[4px]", children: minutes.map((m, i) => /* @__PURE__ */ jsx(
|
|
2963
|
+
/* @__PURE__ */ jsx("div", { "data-column": true, role: "listbox", "aria-label": "Minutes", className: "flex max-h-48 w-[calc(var(--ds-space-10)+8px)] flex-col gap-[4px] overflow-y-auto p-[4px] scroll-p-[4px]", children: minutes.map((m, i) => /* @__PURE__ */ jsx(
|
|
3968
2964
|
"button",
|
|
3969
2965
|
{
|
|
3970
2966
|
type: "button",
|
|
2967
|
+
role: "option",
|
|
3971
2968
|
tabIndex: i === stopOf2("minute", chosenMinute) ? 0 : -1,
|
|
3972
2969
|
onFocus: () => holdStop("minute", i),
|
|
3973
|
-
"
|
|
2970
|
+
"aria-selected": m === parsed.minute,
|
|
3974
2971
|
onMouseDown: (e) => e.preventDefault(),
|
|
3975
2972
|
onClick: () => emitChange(parsed.hour, m, parsed.period),
|
|
3976
2973
|
className: cn(
|
|
@@ -3985,13 +2982,14 @@ function TimePicker({
|
|
|
3985
2982
|
)) }),
|
|
3986
2983
|
!use24Hour && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3987
2984
|
/* @__PURE__ */ jsx("div", { className: "w-px bg-[var(--ds-border-subtle)]" }),
|
|
3988
|
-
/* @__PURE__ */ jsx("div", { "data-column": true, className: "flex flex-col gap-[4px] w-ds-10", children: ["AM", "PM"].map((p, i) => /* @__PURE__ */ jsx(
|
|
2985
|
+
/* @__PURE__ */ jsx("div", { "data-column": true, role: "listbox", "aria-label": "AM or PM", className: "flex flex-col gap-[4px] w-ds-10", children: ["AM", "PM"].map((p, i) => /* @__PURE__ */ jsx(
|
|
3989
2986
|
"button",
|
|
3990
2987
|
{
|
|
3991
2988
|
type: "button",
|
|
2989
|
+
role: "option",
|
|
3992
2990
|
tabIndex: i === stopOf2("period", chosenPeriod) ? 0 : -1,
|
|
3993
2991
|
onFocus: () => holdStop("period", i),
|
|
3994
|
-
"
|
|
2992
|
+
"aria-selected": p === parsed.period,
|
|
3995
2993
|
onMouseDown: (e) => e.preventDefault(),
|
|
3996
2994
|
onClick: () => emitChange(parsed.hour, parsed.minute, p),
|
|
3997
2995
|
className: cn(
|
|
@@ -4054,6 +3052,9 @@ function getPaletteClasses(color, variant) {
|
|
|
4054
3052
|
const styleFn = paletteByVariant[variant] ?? paletteByVariant.subtle;
|
|
4055
3053
|
return styleFn(color);
|
|
4056
3054
|
}
|
|
3055
|
+
var SELECTED = "bg-[var(--ds-accent-subtle)] text-[var(--ds-accent-subtle-text)]";
|
|
3056
|
+
var selectedEdge = (bordered) => bordered ? "border-[length:var(--ds-border-width)] border-[var(--ds-accent-ink)]" : "shadow-[inset_0_0_0_var(--ds-border-width)_var(--ds-accent-ink)]";
|
|
3057
|
+
var LABEL_FOCUS_RING = "has-[>[data-tag-label]:focus-visible]:outline-2 has-[>[data-tag-label]:focus-visible]:outline-solid has-[>[data-tag-label]:focus-visible]:outline-offset-2 has-[>[data-tag-label]:focus-visible]:outline-[var(--ds-focus)] has-[>[data-tag-label]:focus-visible]:shadow-none";
|
|
4057
3058
|
var Tag = forwardRef(function Tag2({
|
|
4058
3059
|
variant = "default",
|
|
4059
3060
|
size = "md",
|
|
@@ -4061,44 +3062,62 @@ var Tag = forwardRef(function Tag2({
|
|
|
4061
3062
|
maxWidth,
|
|
4062
3063
|
onRemove,
|
|
4063
3064
|
onClick,
|
|
3065
|
+
selected,
|
|
4064
3066
|
disabled = false,
|
|
4065
3067
|
className,
|
|
4066
3068
|
children
|
|
4067
3069
|
}, ref) {
|
|
3070
|
+
const chipRef = useRef(null);
|
|
3071
|
+
const setChip = (el) => {
|
|
3072
|
+
chipRef.current = el;
|
|
3073
|
+
if (typeof ref === "function") ref(el);
|
|
3074
|
+
else if (ref) ref.current = el;
|
|
3075
|
+
};
|
|
4068
3076
|
const { ref: truncRef, isTruncated } = useTextOverflow({ lines: 1 });
|
|
4069
3077
|
const handleRemove = (e) => {
|
|
4070
3078
|
e.stopPropagation();
|
|
3079
|
+
focusAfterSelfRemoval(e.currentTarget, { item: chipRef.current });
|
|
4071
3080
|
onRemove?.();
|
|
4072
3081
|
};
|
|
4073
|
-
const
|
|
3082
|
+
const clickable = !!onClick;
|
|
3083
|
+
const isSelected = !!onClick && !!selected;
|
|
3084
|
+
const bordered = variant === "outline" || !color && (variant === "success" || variant === "warning" || variant === "error");
|
|
3085
|
+
const colorClasses = isSelected ? cn(SELECTED, selectedEdge(bordered)) : color ? getPaletteClasses(color, variant) : variantStyles[variant];
|
|
3086
|
+
const label = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3087
|
+
isSelected && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "inline-flex shrink-0 mr-[calc(var(--ds-space-1)*0.5)]", children: /* @__PURE__ */ jsx(Icon, { name: "check", size: size === "sm" ? 10 : 12 }) }),
|
|
3088
|
+
/* @__PURE__ */ jsx("span", { ref: truncRef, className: "truncate min-w-0", children })
|
|
3089
|
+
] });
|
|
4074
3090
|
const tag = /* @__PURE__ */ jsxs(
|
|
4075
3091
|
"span",
|
|
4076
3092
|
{
|
|
4077
|
-
ref,
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
"aria-disabled": disabled || void 0,
|
|
4081
|
-
onClick: onClick && !disabled ? onClick : void 0,
|
|
4082
|
-
onKeyDown: onClick && !disabled ? (e) => {
|
|
4083
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
4084
|
-
e.preventDefault();
|
|
4085
|
-
onClick();
|
|
4086
|
-
}
|
|
4087
|
-
} : void 0,
|
|
3093
|
+
ref: setChip,
|
|
3094
|
+
"aria-disabled": !clickable && disabled || void 0,
|
|
3095
|
+
"data-selected": isSelected ? "" : void 0,
|
|
4088
3096
|
className: cn(
|
|
4089
3097
|
"inline-flex items-center font-medium max-w-full min-w-0 whitespace-nowrap",
|
|
4090
3098
|
"rounded-[var(--ds-radius-sm)]",
|
|
4091
3099
|
"transition-colors duration-[var(--ds-transition-speed)]",
|
|
4092
3100
|
sizeStyles[size],
|
|
4093
3101
|
colorClasses,
|
|
4094
|
-
|
|
3102
|
+
clickable && !disabled && cn("relative cursor-pointer select-none hover:opacity-80", LABEL_FOCUS_RING),
|
|
4095
3103
|
disabled && "opacity-disabled cursor-not-allowed",
|
|
4096
3104
|
className
|
|
4097
3105
|
),
|
|
4098
3106
|
style: maxWidth ? { maxWidth } : void 0,
|
|
4099
3107
|
children: [
|
|
4100
|
-
/* @__PURE__ */ jsx(
|
|
4101
|
-
|
|
3108
|
+
clickable ? /* @__PURE__ */ jsx(
|
|
3109
|
+
"button",
|
|
3110
|
+
{
|
|
3111
|
+
type: "button",
|
|
3112
|
+
"data-tag-label": "",
|
|
3113
|
+
disabled,
|
|
3114
|
+
"aria-pressed": selected,
|
|
3115
|
+
onClick,
|
|
3116
|
+
className: "flex min-w-0 max-w-full items-center cursor-[inherit] outline-none after:absolute after:inset-0 after:content-['']",
|
|
3117
|
+
children: label
|
|
3118
|
+
}
|
|
3119
|
+
) : label,
|
|
3120
|
+
onRemove && !disabled && /* @__PURE__ */ jsx(AutoTooltip, { content: typeof children === "string" ? `Remove ${children}` : "Remove", children: /* @__PURE__ */ jsx(
|
|
4102
3121
|
"button",
|
|
4103
3122
|
{
|
|
4104
3123
|
type: "button",
|
|
@@ -4106,7 +3125,7 @@ var Tag = forwardRef(function Tag2({
|
|
|
4106
3125
|
"data-tag-remove": "",
|
|
4107
3126
|
"aria-label": typeof children === "string" ? `Remove ${children}` : "Remove",
|
|
4108
3127
|
className: cn(
|
|
4109
|
-
"inline-flex items-center justify-center shrink-0",
|
|
3128
|
+
"relative inline-flex items-center justify-center shrink-0",
|
|
4110
3129
|
"rounded-[var(--ds-radius-sm)]",
|
|
4111
3130
|
"opacity-60 hover:opacity-100",
|
|
4112
3131
|
"transition-opacity duration-[var(--ds-transition-speed)] cursor-pointer",
|
|
@@ -4114,7 +3133,7 @@ var Tag = forwardRef(function Tag2({
|
|
|
4114
3133
|
),
|
|
4115
3134
|
children: /* @__PURE__ */ jsx(Icon, { name: "close", size: size === "sm" ? 10 : 12 })
|
|
4116
3135
|
}
|
|
4117
|
-
)
|
|
3136
|
+
) })
|
|
4118
3137
|
]
|
|
4119
3138
|
}
|
|
4120
3139
|
);
|
|
@@ -4163,6 +3182,12 @@ function TagInput({
|
|
|
4163
3182
|
const buttons = Array.from(containerRef.current?.querySelectorAll("[data-tag-remove]") ?? []);
|
|
4164
3183
|
focusAfterRemoval(buttons, pending.index, inputRef.current);
|
|
4165
3184
|
});
|
|
3185
|
+
const overlayMark = useContext(OverlayMarkCtx);
|
|
3186
|
+
const holdsText = input.trim() !== "";
|
|
3187
|
+
useEffect(() => {
|
|
3188
|
+
if (!holdsText || !overlayMark) return;
|
|
3189
|
+
return overlayMark.pend();
|
|
3190
|
+
}, [holdsText, overlayMark]);
|
|
4166
3191
|
const handleKeyDown = useCallback(
|
|
4167
3192
|
(e) => {
|
|
4168
3193
|
if ((e.key === "Enter" || e.key === ",") && input.trim()) {
|
|
@@ -4268,7 +3293,8 @@ function PinInput({
|
|
|
4268
3293
|
size: sizeProp,
|
|
4269
3294
|
className,
|
|
4270
3295
|
error = false,
|
|
4271
|
-
id
|
|
3296
|
+
id,
|
|
3297
|
+
"aria-label": ariaLabel
|
|
4272
3298
|
}) {
|
|
4273
3299
|
const onChange = useReportedChange(onChangeProp, value);
|
|
4274
3300
|
useInputModality();
|
|
@@ -4327,7 +3353,7 @@ function PinInput({
|
|
|
4327
3353
|
"div",
|
|
4328
3354
|
{
|
|
4329
3355
|
role: "group",
|
|
4330
|
-
"aria-label": "PIN input",
|
|
3356
|
+
"aria-label": ariaLabel ?? "PIN input",
|
|
4331
3357
|
"aria-invalid": error || void 0,
|
|
4332
3358
|
className: cn("inline-flex w-fit items-center gap-ds-2", className),
|
|
4333
3359
|
children: digits.map((digit, i) => /* @__PURE__ */ jsx(
|
|
@@ -4487,7 +3513,7 @@ function Rating({
|
|
|
4487
3513
|
{
|
|
4488
3514
|
role: readOnly ? "img" : "radiogroup",
|
|
4489
3515
|
id: control.id,
|
|
4490
|
-
"aria-label": readOnly
|
|
3516
|
+
"aria-label": readOnly ? `${control.label ?? "Rating"}: ${value} out of ${max}` : control.labelId ? void 0 : control.label ?? `Rating: ${value} out of ${max}`,
|
|
4491
3517
|
"aria-labelledby": readOnly ? void 0 : control.labelId,
|
|
4492
3518
|
"aria-describedby": control.describedBy,
|
|
4493
3519
|
"aria-invalid": readOnly ? void 0 : control.invalid || void 0,
|
|
@@ -4575,7 +3601,8 @@ function ColorPicker({
|
|
|
4575
3601
|
swatches = DEFAULT_SWATCHES,
|
|
4576
3602
|
disabled = false,
|
|
4577
3603
|
className,
|
|
4578
|
-
error = false
|
|
3604
|
+
error = false,
|
|
3605
|
+
"aria-label": ariaLabel
|
|
4579
3606
|
}) {
|
|
4580
3607
|
const onChange = useReportedChange(onChangeProp, value);
|
|
4581
3608
|
useInputModality();
|
|
@@ -4640,6 +3667,8 @@ function ColorPicker({
|
|
|
4640
3667
|
return /* @__PURE__ */ jsxs(
|
|
4641
3668
|
"div",
|
|
4642
3669
|
{
|
|
3670
|
+
role: "group",
|
|
3671
|
+
"aria-label": ariaLabel,
|
|
4643
3672
|
"aria-invalid": error || void 0,
|
|
4644
3673
|
className: cn(
|
|
4645
3674
|
"w-full max-w-64 p-ds-3 space-y-ds-3",
|
|
@@ -4789,18 +3818,33 @@ var Alert = forwardRef(function Alert2({
|
|
|
4789
3818
|
actions,
|
|
4790
3819
|
placement = "inline",
|
|
4791
3820
|
expandableContent,
|
|
3821
|
+
consent,
|
|
3822
|
+
confirmation,
|
|
4792
3823
|
className
|
|
4793
3824
|
}, ref) {
|
|
3825
|
+
const titleId = useId();
|
|
3826
|
+
const confirmationRef = useRef(null);
|
|
3827
|
+
const confirming = !!consent && confirmation != null;
|
|
3828
|
+
useEffect(() => {
|
|
3829
|
+
if (confirming) confirmationRef.current?.focus();
|
|
3830
|
+
}, [confirming]);
|
|
3831
|
+
const rootRef = useRef(null);
|
|
3832
|
+
const setRoot = (el) => {
|
|
3833
|
+
rootRef.current = el;
|
|
3834
|
+
if (typeof ref === "function") ref(el);
|
|
3835
|
+
else if (ref) ref.current = el;
|
|
3836
|
+
};
|
|
4794
3837
|
const [detailsExpanded, setDetailsExpanded] = useState(false);
|
|
4795
3838
|
const isMobile = useBreakpoint("sm");
|
|
4796
|
-
const resolvedActions = actions ?? (action ? [action] : []);
|
|
3839
|
+
const resolvedActions = consent || confirming ? [] : actions ?? (action ? [action] : []);
|
|
4797
3840
|
const shouldCollapseActions = isMobile && resolvedActions.length > 1;
|
|
4798
|
-
const placementClasses = placement === "page-top" ? "sticky top-0 z-[var(--ds-z-sticky)] rounded-none" : placement === "section-top" ? "rounded-[var(--ds-radius-md)] my-ds-4" : "rounded-[var(--ds-radius-md)]";
|
|
3841
|
+
const placementClasses = placement === "page-top" && !consent ? "sticky top-0 z-[var(--ds-z-sticky)] rounded-none" : placement === "section-top" ? "rounded-[var(--ds-radius-md)] my-ds-4" : "rounded-[var(--ds-radius-md)]";
|
|
4799
3842
|
return /* @__PURE__ */ jsxs(
|
|
4800
3843
|
"div",
|
|
4801
3844
|
{
|
|
4802
|
-
ref,
|
|
4803
|
-
role: "alert",
|
|
3845
|
+
ref: setRoot,
|
|
3846
|
+
role: consent ? "region" : variant === "error" || variant === "warning" ? "alert" : "status",
|
|
3847
|
+
"aria-labelledby": consent ? titleId : void 0,
|
|
4804
3848
|
className: cn(
|
|
4805
3849
|
"flex items-start gap-ds-3 p-ds-4",
|
|
4806
3850
|
"border-[length:var(--ds-border-width)]",
|
|
@@ -4814,7 +3858,7 @@ var Alert = forwardRef(function Alert2({
|
|
|
4814
3858
|
/* @__PURE__ */ jsx("div", { className: cn("mt-[0.3125em] w-3 h-3 shrink-0 rounded-[var(--ds-radius-sm)]", indicators[variant]) }),
|
|
4815
3859
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
4816
3860
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-ds-3", children: [
|
|
4817
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)]", children: title }),
|
|
3861
|
+
/* @__PURE__ */ jsx("p", { id: titleId, className: "text-sm font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)]", children: title }),
|
|
4818
3862
|
resolvedActions.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: shouldCollapseActions ? /* @__PURE__ */ jsx(
|
|
4819
3863
|
DropdownMenu,
|
|
4820
3864
|
{
|
|
@@ -4864,7 +3908,34 @@ var Alert = forwardRef(function Alert2({
|
|
|
4864
3908
|
);
|
|
4865
3909
|
}) })
|
|
4866
3910
|
] }),
|
|
4867
|
-
|
|
3911
|
+
confirming ? (
|
|
3912
|
+
// GOV.UK's cookie banner: the confirmation in the choices' place, announced, with focus on it
|
|
3913
|
+
/* @__PURE__ */ jsx("div", { ref: confirmationRef, role: "alert", tabIndex: -1, className: "mt-ds-1 text-xs text-[var(--ds-text-secondary)] outline-none", children: confirmation })
|
|
3914
|
+
) : children && /* @__PURE__ */ jsx("div", { className: "mt-ds-1 text-xs text-[var(--ds-text-secondary)]", children }),
|
|
3915
|
+
consent && !confirming && // two choices of equal weight, the alert's own action look, side by side at any width (sharing a phone's row);
|
|
3916
|
+
// never a menu
|
|
3917
|
+
/* @__PURE__ */ jsx("div", { "data-alert-consent": "", className: "mt-ds-3 flex flex-wrap gap-ds-2", children: [consent.accept, consent.reject].map((choice) => choice.primary ? (
|
|
3918
|
+
// a page that insists on one primary choice: the library's primary Button in the other choice's box, its
|
|
3919
|
+
// padding, corners and height, wrapping as it does, so the two share a row's height and a phone's row
|
|
3920
|
+
// equally. Its height and padding go in its style: its size's classes set them, and a class can't be relied on
|
|
3921
|
+
// to undo another
|
|
3922
|
+
/* @__PURE__ */ jsx(Button, { type: "button", size: "xs", onClick: choice.onClick, style: { height: "auto", paddingBlock: "var(--ds-space-1)", paddingInline: "var(--ds-space-2\\.5)" }, className: "min-h-ds-6 whitespace-normal rounded-[var(--ds-radius-sm)] max-sm:flex-1 max-sm:min-h-[var(--ds-control-height-sm)]", children: choice.label }, choice.label)
|
|
3923
|
+
) : /* @__PURE__ */ jsx(
|
|
3924
|
+
"button",
|
|
3925
|
+
{
|
|
3926
|
+
type: "button",
|
|
3927
|
+
onClick: choice.onClick,
|
|
3928
|
+
className: cn(
|
|
3929
|
+
"text-xs font-medium px-ds-2.5 py-ds-1 rounded-[var(--ds-radius-sm)]",
|
|
3930
|
+
"transition-colors cursor-pointer max-sm:flex-1 max-sm:min-h-[var(--ds-control-height-sm)]",
|
|
3931
|
+
"border-[length:var(--ds-border-width)] border-current",
|
|
3932
|
+
actionColorsByVariant[variant],
|
|
3933
|
+
FOCUS_RING
|
|
3934
|
+
),
|
|
3935
|
+
children: choice.label
|
|
3936
|
+
},
|
|
3937
|
+
choice.label
|
|
3938
|
+
)) }),
|
|
4868
3939
|
expandableContent && /* @__PURE__ */ jsxs("div", { className: "mt-ds-2", children: [
|
|
4869
3940
|
/* @__PURE__ */ jsxs(
|
|
4870
3941
|
"button",
|
|
@@ -4895,13 +3966,21 @@ var Alert = forwardRef(function Alert2({
|
|
|
4895
3966
|
detailsExpanded && /* @__PURE__ */ jsx("div", { className: "mt-ds-2 text-xs text-[var(--ds-text-secondary)] border-l-2 border-current/20 pl-ds-3", children: expandableContent })
|
|
4896
3967
|
] })
|
|
4897
3968
|
] }),
|
|
4898
|
-
dismissible &&
|
|
4899
|
-
|
|
3969
|
+
dismissible && (!consent || confirming) && // Sprint 25.8.7 item 33: the library's icon Button, so its name shows as its one tooltip, with a 24 px target; at
|
|
3970
|
+
// rest the muted cross where it was (the margin takes back the box's room), on hover the alert's own buttons'
|
|
3971
|
+
// tint. Its alert goes with it, so focus goes to a neighbour (focusAfterSelfRemoval), never to the page
|
|
3972
|
+
/* @__PURE__ */ jsx(
|
|
3973
|
+
Button,
|
|
4900
3974
|
{
|
|
4901
3975
|
type: "button",
|
|
4902
|
-
|
|
4903
|
-
|
|
3976
|
+
variant: "ghost",
|
|
3977
|
+
size: "icon-xs",
|
|
4904
3978
|
"aria-label": "Dismiss",
|
|
3979
|
+
onClick: (e) => {
|
|
3980
|
+
focusAfterSelfRemoval(e.currentTarget, { item: rootRef.current });
|
|
3981
|
+
onDismiss?.();
|
|
3982
|
+
},
|
|
3983
|
+
className: cn("-m-ds-1 shrink-0", actionColorsByVariant[variant], "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)]"),
|
|
4905
3984
|
children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 16 })
|
|
4906
3985
|
}
|
|
4907
3986
|
)
|
|
@@ -5256,7 +4335,10 @@ function TransferList({
|
|
|
5256
4335
|
"button",
|
|
5257
4336
|
{
|
|
5258
4337
|
type: "button",
|
|
5259
|
-
onClick:
|
|
4338
|
+
onClick: (e) => {
|
|
4339
|
+
focusAfterSelfRemoval(e.currentTarget);
|
|
4340
|
+
moveAllRight();
|
|
4341
|
+
},
|
|
5260
4342
|
disabled: !available.filter((i) => !i.disabled).length,
|
|
5261
4343
|
"aria-label": isStacked ? "Move all down" : "Move all right",
|
|
5262
4344
|
className: cn(actionButtonClass),
|
|
@@ -5267,7 +4349,10 @@ function TransferList({
|
|
|
5267
4349
|
"button",
|
|
5268
4350
|
{
|
|
5269
4351
|
type: "button",
|
|
5270
|
-
onClick:
|
|
4352
|
+
onClick: (e) => {
|
|
4353
|
+
focusAfterSelfRemoval(e.currentTarget);
|
|
4354
|
+
moveRight();
|
|
4355
|
+
},
|
|
5271
4356
|
disabled: !checkedAvailable.size,
|
|
5272
4357
|
"aria-label": isStacked ? "Move selected down" : "Move selected right",
|
|
5273
4358
|
className: cn(actionButtonClass),
|
|
@@ -5278,7 +4363,10 @@ function TransferList({
|
|
|
5278
4363
|
"button",
|
|
5279
4364
|
{
|
|
5280
4365
|
type: "button",
|
|
5281
|
-
onClick:
|
|
4366
|
+
onClick: (e) => {
|
|
4367
|
+
focusAfterSelfRemoval(e.currentTarget);
|
|
4368
|
+
moveLeft();
|
|
4369
|
+
},
|
|
5282
4370
|
disabled: !checkedSelected.size,
|
|
5283
4371
|
"aria-label": isStacked ? "Move selected up" : "Move selected left",
|
|
5284
4372
|
className: cn(actionButtonClass),
|
|
@@ -5289,7 +4377,10 @@ function TransferList({
|
|
|
5289
4377
|
"button",
|
|
5290
4378
|
{
|
|
5291
4379
|
type: "button",
|
|
5292
|
-
onClick:
|
|
4380
|
+
onClick: (e) => {
|
|
4381
|
+
focusAfterSelfRemoval(e.currentTarget);
|
|
4382
|
+
moveAllLeft();
|
|
4383
|
+
},
|
|
5293
4384
|
disabled: !selected.filter((i) => !i.disabled).length,
|
|
5294
4385
|
"aria-label": isStacked ? "Move all up" : "Move all left",
|
|
5295
4386
|
className: cn(actionButtonClass),
|
|
@@ -5949,7 +5040,7 @@ var CardHeader = forwardRef(function CardHeader2(allProps, ref) {
|
|
|
5949
5040
|
const menu = menuItems ? /* @__PURE__ */ jsx(
|
|
5950
5041
|
DropdownMenu,
|
|
5951
5042
|
{
|
|
5952
|
-
trigger: /* @__PURE__ */ jsx(
|
|
5043
|
+
trigger: /* @__PURE__ */ jsx(AutoTooltip, { content: "More actions", children: /* @__PURE__ */ jsx(
|
|
5953
5044
|
"button",
|
|
5954
5045
|
{
|
|
5955
5046
|
type: "button",
|
|
@@ -5963,7 +5054,7 @@ var CardHeader = forwardRef(function CardHeader2(allProps, ref) {
|
|
|
5963
5054
|
onClick: (e) => e.stopPropagation(),
|
|
5964
5055
|
children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: 16 })
|
|
5965
5056
|
}
|
|
5966
|
-
),
|
|
5057
|
+
) }),
|
|
5967
5058
|
items: menuItems
|
|
5968
5059
|
}
|
|
5969
5060
|
) : null;
|
|
@@ -6574,12 +5665,14 @@ function actionsAreBadges(actions) {
|
|
|
6574
5665
|
const items = Children.toArray(actions);
|
|
6575
5666
|
return items.length > 0 && items.every((item) => isValidElement(item) && (item.type === Fragment$1 ? actionsAreBadges(item.props.children) : elementType(item.type) === Badge));
|
|
6576
5667
|
}
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
|
|
5668
|
+
var SKELETON_ROWS = 5;
|
|
5669
|
+
var SKELETON_WIDTHS = ["72%", "48%", "60%", "36%", "54%"];
|
|
5670
|
+
var LOADING_LABEL = "Loading table data";
|
|
5671
|
+
function RefreshLine({ className }) {
|
|
5672
|
+
return /* @__PURE__ */ jsx("div", { "aria-hidden": "true", "data-table-refreshing": "", className: cn("pointer-events-none absolute top-0 z-20 h-[2px] overflow-hidden", className), children: /* @__PURE__ */ jsx("div", { className: "h-full w-1/3 bg-[var(--ds-accent-primary)] animate-[gs-indeterminate_1.5s_ease-in-out_infinite] motion-reduce:animate-none motion-reduce:w-full motion-reduce:opacity-50" }) });
|
|
5673
|
+
}
|
|
5674
|
+
function SkeletonLine({ width, end = false, className }) {
|
|
5675
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex h-5 items-center", end && "justify-end", className), children: /* @__PURE__ */ jsx(Skeleton, { variant: "custom", width, height: "0.75rem" }) });
|
|
6583
5676
|
}
|
|
6584
5677
|
var TITLE_CLASSES = TITLE_TEXT;
|
|
6585
5678
|
var FRAME_CLASSES = cn(
|
|
@@ -6824,6 +5917,11 @@ function Table({
|
|
|
6824
5917
|
useEffect(() => {
|
|
6825
5918
|
if (unsortable) warnOnce("Table", `the column "${unsortable}" is sortable, but its cells are elements, which can't be compared: give it a sortValue, (row) => the name, number or date it shows (data_display#1).`);
|
|
6826
5919
|
}, [unsortable]);
|
|
5920
|
+
const pageSorts = !!onSortChange;
|
|
5921
|
+
const refused = pageSorts ? "" : columns.filter((col) => col.sortable && !canSort.has(col.key)).map((col) => col.key).join(", ");
|
|
5922
|
+
useEffect(() => {
|
|
5923
|
+
if (refused) warnOnce("Table", `the column "${refused}" is marked sortable, but its cells are elements the Table can't compare, so it draws no sort button: give it a sortValue, (row) => the name, number or date it shows, or sort the rows yourself with sortKey and onSortChange (data_display#1).`);
|
|
5924
|
+
}, [refused]);
|
|
6827
5925
|
useEffect(() => {
|
|
6828
5926
|
if (pager && data.length !== pager.totalItems) warnOnce("Table", `the pager counts ${pager.totalItems} rows but data holds ${data.length}: give the table and usePagination the same rows, every row of the list, and the table draws the pager's part (Sprint 25.13 A3).`);
|
|
6829
5927
|
}, [pager, data.length]);
|
|
@@ -6843,7 +5941,16 @@ function Table({
|
|
|
6843
5941
|
if (allSelected) onSelectionChange?.(selectedRows.filter((r) => !shown.has(r)));
|
|
6844
5942
|
else onSelectionChange?.([...selectedRows.filter((r) => !shown.has(r)), ...drawnIdx]);
|
|
6845
5943
|
};
|
|
6846
|
-
const
|
|
5944
|
+
const anchor = useRef(null);
|
|
5945
|
+
const toggleRow = (idx, shiftKey2 = false) => {
|
|
5946
|
+
const from = anchor.current === null ? -1 : drawnIdx.indexOf(anchor.current);
|
|
5947
|
+
const to = drawnIdx.indexOf(idx);
|
|
5948
|
+
anchor.current = idx;
|
|
5949
|
+
if (shiftKey2 && from >= 0 && to >= 0 && from !== to) {
|
|
5950
|
+
const run = drawnIdx.slice(Math.min(from, to), Math.max(from, to) + 1);
|
|
5951
|
+
onSelectionChange?.([...selectedRows.filter((r) => !run.includes(r)), ...run]);
|
|
5952
|
+
return;
|
|
5953
|
+
}
|
|
6847
5954
|
if (selectedSet.has(idx)) onSelectionChange?.(selectedRows.filter((r) => r !== idx));
|
|
6848
5955
|
else onSelectionChange?.([...selectedRows, idx]);
|
|
6849
5956
|
};
|
|
@@ -6871,6 +5978,9 @@ function Table({
|
|
|
6871
5978
|
const narrowScreen = useBreakpoint(mobileBreakpoint);
|
|
6872
5979
|
const { cards: isMobile, rootRef } = useCardsSwitch(narrowScreen, cardsBelow, title);
|
|
6873
5980
|
useRevealFocus(rootRef, isMobile);
|
|
5981
|
+
useFocusKeptInList(rootRef);
|
|
5982
|
+
const [cardsEl, setCardsEl] = useState(null);
|
|
5983
|
+
useKeyboardScroll(cardsEl, title ?? ariaLabel ?? "Table", isMobile);
|
|
6874
5984
|
const setRoot = useCallback((node) => {
|
|
6875
5985
|
rootRef.current = node;
|
|
6876
5986
|
if (typeof ref === "function") ref(node);
|
|
@@ -6998,8 +6108,14 @@ function Table({
|
|
|
6998
6108
|
cardHeading,
|
|
6999
6109
|
body
|
|
7000
6110
|
] });
|
|
7001
|
-
const
|
|
6111
|
+
const paged = !!pager && data.length > 0;
|
|
6112
|
+
const control = paged ? /* @__PURE__ */ jsx(Pagination, { ...pager.props }) : null;
|
|
7002
6113
|
const listRoot = control ? void 0 : setRoot;
|
|
6114
|
+
const cardsAreRoot = !title && !paged;
|
|
6115
|
+
const setCards = useCallback((el) => {
|
|
6116
|
+
setCardsEl(el);
|
|
6117
|
+
if (cardsAreRoot) setRoot(el);
|
|
6118
|
+
}, [cardsAreRoot, setRoot]);
|
|
7003
6119
|
const listClass = control ? void 0 : className;
|
|
7004
6120
|
const withControl = (list2) => control ? /* @__PURE__ */ jsxs("div", { ref: setRoot, "data-gs-paged": "", className: cn("flex flex-col min-w-0", className), children: [
|
|
7005
6121
|
list2,
|
|
@@ -7033,15 +6149,23 @@ function Table({
|
|
|
7033
6149
|
(same ?? (row.tabIndex >= 0 ? row : controls[0]))?.focus({ preventScroll: true });
|
|
7034
6150
|
}, [isMobile, rootRef]);
|
|
7035
6151
|
if (isMobile) {
|
|
7036
|
-
if (loading) {
|
|
7037
|
-
|
|
7038
|
-
|
|
6152
|
+
if (loading && data.length === 0) {
|
|
6153
|
+
const skeletonCards = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6154
|
+
/* @__PURE__ */ jsx("span", { role: "status", className: "sr-only", children: LOADING_LABEL }),
|
|
6155
|
+
/* @__PURE__ */ jsx("div", { "data-table-skeleton": "", className: "flex flex-col gap-ds-3", "aria-busy": "true", children: Array.from({ length: 3 }, (_, r) => /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] rounded-[var(--ds-radius-md)] bg-[var(--ds-bg-surface)] p-ds-4 space-y-ds-3", children: columns.slice(0, 4).map((col, c) => /* @__PURE__ */ jsxs("div", { className: "flex justify-between gap-ds-2", children: [
|
|
6156
|
+
/* @__PURE__ */ jsx(SkeletonLine, { width: "56%", className: "flex-1" }),
|
|
6157
|
+
/* @__PURE__ */ jsx(SkeletonLine, { width: SKELETON_WIDTHS[(r + c) % SKELETON_WIDTHS.length], end: true, className: "flex-1" })
|
|
6158
|
+
] }, col.key)) }, r)) })
|
|
6159
|
+
] });
|
|
6160
|
+
if (title) return titledCards(skeletonCards);
|
|
6161
|
+
return /* @__PURE__ */ jsx("div", { ref: setRoot, "data-ds-list": "", "data-gs": "table", className, children: skeletonCards });
|
|
7039
6162
|
}
|
|
7040
6163
|
if (data.length === 0 && emptyState) {
|
|
7041
6164
|
if (title) return titledCards(/* @__PURE__ */ jsx("div", { className: "py-ds-10 text-center text-sm text-[var(--ds-text-muted)]", children: emptyState }));
|
|
7042
6165
|
return /* @__PURE__ */ jsx("div", { ref: setRoot, "data-ds-list": "", "data-gs": "table", className: cn("py-ds-10 text-center text-sm text-[var(--ds-text-muted)]", className), children: emptyState });
|
|
7043
6166
|
}
|
|
7044
|
-
const cards = /* @__PURE__ */ jsx(TableCardCtx, { value: true, children: /* @__PURE__ */ jsx(RowsCtx, { value: true, children: /* @__PURE__ */ jsxs("div", { ref:
|
|
6167
|
+
const cards = /* @__PURE__ */ jsx(TableCardCtx, { value: true, children: /* @__PURE__ */ jsx(RowsCtx, { value: true, children: /* @__PURE__ */ jsxs("div", { ref: setCards, "data-ds-list": title ? void 0 : "", "data-gs": title ? void 0 : "table", className: cn("relative flex flex-col gap-ds-3 overflow-y-auto -m-[4px] p-[4px] scroll-p-[4px]", FOCUS_INSET, title ? "min-h-0" : listClass), onFocus: title ? void 0 : noteFocus, onBlur: title ? void 0 : forgetFocus, children: [
|
|
6168
|
+
loading && data.length > 0 && /* @__PURE__ */ jsx(RefreshLine, { className: "inset-x-[4px] rounded-full" }),
|
|
7045
6169
|
selectable && /* @__PURE__ */ jsx("span", { hidden: true, id: `${headingId}-select`, children: "Select" }),
|
|
7046
6170
|
drawn.map(({ row, originalIdx }) => {
|
|
7047
6171
|
const isSelected = selectedSet.has(originalIdx);
|
|
@@ -7085,7 +6209,7 @@ function Table({
|
|
|
7085
6209
|
} : void 0,
|
|
7086
6210
|
children: [
|
|
7087
6211
|
selectable && // "Select" and the row's name, as in the table (T15)
|
|
7088
|
-
/* @__PURE__ */ jsx(Checkbox, { checked: isSelected, onChange: () => toggleRow(originalIdx), "aria-labelledby": nameIndex >= 0 ? `${headingId}-select ${headingId}-card-name-${idPart(id)}` : `${headingId}-select` }),
|
|
6212
|
+
/* @__PURE__ */ jsx(Checkbox, { checked: isSelected, onChange: (_, { shiftKey: shiftKey2 }) => toggleRow(originalIdx, shiftKey2), "aria-labelledby": nameIndex >= 0 ? `${headingId}-select ${headingId}-card-name-${idPart(id)}` : `${headingId}-select` }),
|
|
7089
6213
|
columns.map((col, c) => /* @__PURE__ */ jsxs("div", { className: "flex justify-between gap-ds-2 text-sm", children: [
|
|
7090
6214
|
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-[var(--ds-text-secondary)] font-medium text-xs uppercase tracking-wider", children: col.header }),
|
|
7091
6215
|
/* @__PURE__ */ jsx(CardValue, { value: row[col.key], id: lead + c === nameIndex ? `${headingId}-card-name-${idPart(id)}` : void 0 })
|
|
@@ -7129,9 +6253,10 @@ function Table({
|
|
|
7129
6253
|
return withControl(title ? titledCards(cards) : cards);
|
|
7130
6254
|
}
|
|
7131
6255
|
const cellCount = columns.length + lead;
|
|
7132
|
-
const table = /* @__PURE__ */ jsxs("table", { ref: tableRef, className: cn("w-full text-sm", PINNED_LAYERS), ...title ? { "aria-labelledby": titleId, "aria-describedby": description ? descriptionId : void 0 } : ariaLabel ? { "aria-label": ariaLabel } : {}, children: [
|
|
6256
|
+
const table = /* @__PURE__ */ jsxs("table", { ref: tableRef, "aria-busy": loading || void 0, className: cn("w-full text-sm", PINNED_LAYERS), ...title ? { "aria-labelledby": titleId, "aria-describedby": description ? descriptionId : void 0 } : ariaLabel ? { "aria-label": ariaLabel } : {}, children: [
|
|
7133
6257
|
/* @__PURE__ */ jsx("thead", { className: cn("bg-[var(--ds-bg-muted)]", stickyHeader && "sticky top-0 z-10"), children: /* @__PURE__ */ jsxs("tr", { className: "border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] [--gs-row-tint:var(--ds-bg-muted)]", children: [
|
|
7134
|
-
selectable &&
|
|
6258
|
+
selectable && // data-ds-select-all: the selection's own control, where a BulkActionBar's Clear selection sends focus
|
|
6259
|
+
/* @__PURE__ */ jsx("th", { "data-ds-select-all": "", className: cn("w-10", density === "compact" ? "px-ds-2 py-ds-2" : "px-ds-3 py-ds-3"), style: pinStyle(0, cellCount), children: /* @__PURE__ */ jsx(
|
|
7135
6260
|
Checkbox,
|
|
7136
6261
|
{
|
|
7137
6262
|
checked: allSelected,
|
|
@@ -7142,8 +6267,8 @@ function Table({
|
|
|
7142
6267
|
) }),
|
|
7143
6268
|
expandable && /* @__PURE__ */ jsx("th", { className: cn("w-8", density === "compact" ? "px-ds-1 py-ds-2" : "px-ds-2 py-ds-3"), style: pinStyle(selectable ? 1 : 0, cellCount) }),
|
|
7144
6269
|
columns.map((col, c) => {
|
|
7145
|
-
const isSortable = col.header.trim() !== "" && (col.sortable ?? (!!sortable && canSort.has(col.key)));
|
|
7146
|
-
const isActiveSort = sortKey === col.key && !!sortDir && unsortable !== col.key;
|
|
6270
|
+
const isSortable = col.header.trim() !== "" && (pageSorts ? col.sortable ?? (!!sortable && canSort.has(col.key)) : (col.sortable ?? !!sortable) && canSort.has(col.key));
|
|
6271
|
+
const isActiveSort = sortKey === col.key && !!sortDir && (pageSorts || unsortable !== col.key);
|
|
7147
6272
|
const headerKind = kindOf2(col);
|
|
7148
6273
|
const headerAlign = col.align ?? (headerKind === "number" ? "right" : "left");
|
|
7149
6274
|
const shrink = (headerKind === "number" || headerKind === "date") && !col.maxWidth;
|
|
@@ -7171,21 +6296,18 @@ function Table({
|
|
|
7171
6296
|
"inline-flex items-center gap-ds-1 uppercase tracking-wider cursor-pointer select-none",
|
|
7172
6297
|
"[font:inherit] text-inherit hover:text-[var(--ds-text-primary)]",
|
|
7173
6298
|
"rounded-[var(--ds-radius-sm)]",
|
|
6299
|
+
// in a right-aligned column the indicator goes before the label, so the label ends where the
|
|
6300
|
+
// column's values end; the sorted column's label in full colour (the look check, 14 October).
|
|
6301
|
+
// Set at the line's top, not its baseline: reversed, the button takes its baseline from the
|
|
6302
|
+
// indicator, which has no text, and stood 2 px above the other headers' labels
|
|
6303
|
+
headerAlign === "right" && "flex-row-reverse",
|
|
6304
|
+
"align-top",
|
|
6305
|
+
isActiveSort && "text-[var(--ds-text-primary)]",
|
|
7174
6306
|
FOCUS_RING
|
|
7175
6307
|
),
|
|
7176
6308
|
children: [
|
|
7177
6309
|
col.header,
|
|
7178
|
-
/* @__PURE__ */ jsx(
|
|
7179
|
-
Icon,
|
|
7180
|
-
{
|
|
7181
|
-
name: "chevron-right",
|
|
7182
|
-
size: 12,
|
|
7183
|
-
className: cn(
|
|
7184
|
-
"transition-transform",
|
|
7185
|
-
!isActiveSort ? "invisible" : sortDir === "asc" ? "-rotate-90" : "rotate-90"
|
|
7186
|
-
)
|
|
7187
|
-
}
|
|
7188
|
-
)
|
|
6310
|
+
/* @__PURE__ */ jsx(SortIndicator, { sorted: isActiveSort ? sortDir : false })
|
|
7189
6311
|
]
|
|
7190
6312
|
}
|
|
7191
6313
|
)
|
|
@@ -7195,14 +6317,15 @@ function Table({
|
|
|
7195
6317
|
);
|
|
7196
6318
|
})
|
|
7197
6319
|
] }) }),
|
|
7198
|
-
/* @__PURE__ */ jsx("tbody", { children: /* @__PURE__ */ jsx(RowsCtx, { value: true, children: loading
|
|
7199
|
-
|
|
7200
|
-
|
|
7201
|
-
|
|
7202
|
-
className: "px-ds-
|
|
7203
|
-
|
|
7204
|
-
|
|
7205
|
-
|
|
6320
|
+
/* @__PURE__ */ jsx("tbody", { children: /* @__PURE__ */ jsx(RowsCtx, { value: true, children: loading && data.length === 0 ? (
|
|
6321
|
+
// the rows' shape on a first load (item 16), each cell's bar where its text will be; the rows are hidden
|
|
6322
|
+
// from a screen reader, which hears the status beside the table
|
|
6323
|
+
Array.from({ length: SKELETON_ROWS }, (_, r) => /* @__PURE__ */ jsxs("tr", { "data-table-skeleton": "", className: "border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] last:border-b-0", children: [
|
|
6324
|
+
selectable && /* @__PURE__ */ jsx("td", { "aria-hidden": true, className: cn("w-10", density === "compact" ? "px-ds-2 py-ds-2" : "px-ds-3 py-ds-3"), children: /* @__PURE__ */ jsx(SkeletonLine, { width: "16px" }) }),
|
|
6325
|
+
expandable && /* @__PURE__ */ jsx("td", { "aria-hidden": true, className: cn("w-8", density === "compact" ? "px-ds-1 py-ds-2" : "px-ds-2 py-ds-3") }),
|
|
6326
|
+
columns.map((col, c) => /* @__PURE__ */ jsx("td", { className: density === "compact" ? "px-ds-3 py-ds-2" : "px-ds-4 py-ds-3", children: /* @__PURE__ */ jsx("div", { "aria-hidden": true, children: /* @__PURE__ */ jsx(SkeletonLine, { width: SKELETON_WIDTHS[(r + c) % SKELETON_WIDTHS.length], end: (col.align ?? (kindOf2(col) === "number" ? "right" : "left")) === "right" }) }) }, col.key))
|
|
6327
|
+
] }, `skeleton-${r}`))
|
|
6328
|
+
) : data.length === 0 && emptyState ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
|
|
7206
6329
|
"td",
|
|
7207
6330
|
{
|
|
7208
6331
|
colSpan: cellCount,
|
|
@@ -7246,8 +6369,8 @@ function Table({
|
|
|
7246
6369
|
}
|
|
7247
6370
|
} : void 0,
|
|
7248
6371
|
children: [
|
|
7249
|
-
selectable && /* @__PURE__ */ jsx("td", { className: cn("w-10", density === "compact" ? "px-ds-2 py-ds-2" : "px-ds-3 py-ds-3", pinFocus(0, cellCount)), style: pinStyle(0, cellCount), children: /* @__PURE__ */ jsx(Checkbox, { checked: isSelected, onChange: () => toggleRow(originalIdx), "aria-labelledby": nameIndex >= 0 ? `${headingId}-select ${headingId}-name-${idPart(id)}` : `${headingId}-select` }) }),
|
|
7250
|
-
expandable && /* @__PURE__ */ jsx("td", { className: cn("w-8", density === "compact" ? "px-ds-1 py-ds-2" : "px-ds-2 py-ds-3", pinFocus(selectable ? 1 : 0, cellCount)), style: pinStyle(selectable ? 1 : 0, cellCount), children: /* @__PURE__ */ jsx(
|
|
6372
|
+
selectable && /* @__PURE__ */ jsx("td", { className: cn("w-10", density === "compact" ? "px-ds-2 py-ds-2" : "px-ds-3 py-ds-3", pinFocus(0, cellCount)), style: pinStyle(0, cellCount), children: /* @__PURE__ */ jsx(Checkbox, { checked: isSelected, onChange: (_, { shiftKey: shiftKey2 }) => toggleRow(originalIdx, shiftKey2), "aria-labelledby": nameIndex >= 0 ? `${headingId}-select ${headingId}-name-${idPart(id)}` : `${headingId}-select` }) }),
|
|
6373
|
+
expandable && /* @__PURE__ */ jsx("td", { className: cn("w-8", density === "compact" ? "px-ds-1 py-ds-2" : "px-ds-2 py-ds-3", pinFocus(selectable ? 1 : 0, cellCount)), style: pinStyle(selectable ? 1 : 0, cellCount), children: /* @__PURE__ */ jsx(AutoTooltip, { content: "Details", children: /* @__PURE__ */ jsx(
|
|
7251
6374
|
"button",
|
|
7252
6375
|
{
|
|
7253
6376
|
type: "button",
|
|
@@ -7264,7 +6387,7 @@ function Table({
|
|
|
7264
6387
|
}
|
|
7265
6388
|
)
|
|
7266
6389
|
}
|
|
7267
|
-
) }),
|
|
6390
|
+
) }) }),
|
|
7268
6391
|
columns.map((col, c) => {
|
|
7269
6392
|
const truncLines = col.truncate === true ? 1 : col.truncate ? col.truncate.lines : 0;
|
|
7270
6393
|
const kind = kindOf2(col);
|
|
@@ -7274,9 +6397,9 @@ function Table({
|
|
|
7274
6397
|
const whole2 = !kind && renderedKinds.has(col.key);
|
|
7275
6398
|
let inner;
|
|
7276
6399
|
if (truncLines > 0) {
|
|
7277
|
-
inner = /* @__PURE__ */ jsx(
|
|
6400
|
+
inner = /* @__PURE__ */ jsx(CutCell, { lines: truncLines, children: cellContent });
|
|
7278
6401
|
} else if (kind === "email") {
|
|
7279
|
-
inner = /* @__PURE__ */ jsx(
|
|
6402
|
+
inner = /* @__PURE__ */ jsx(CutEmail, { children: cellContent });
|
|
7280
6403
|
} else {
|
|
7281
6404
|
inner = cellContent;
|
|
7282
6405
|
}
|
|
@@ -7335,10 +6458,12 @@ function Table({
|
|
|
7335
6458
|
ref: listRoot,
|
|
7336
6459
|
"data-ds-list": "",
|
|
7337
6460
|
"data-gs": "table",
|
|
7338
|
-
className: cn("w-full min-w-0 flex flex-col", FRAME_CLASSES, FRAME_FOCUS_RING, control && "min-h-0", listClass),
|
|
6461
|
+
className: cn("relative w-full min-w-0 flex flex-col", FRAME_CLASSES, FRAME_FOCUS_RING, control && "min-h-0", listClass),
|
|
7339
6462
|
onFocus: noteFocus,
|
|
7340
6463
|
onBlur: forgetFocus,
|
|
7341
6464
|
children: [
|
|
6465
|
+
loading && data.length > 0 && /* @__PURE__ */ jsx(RefreshLine, { className: "inset-x-0 rounded-t-[inherit]" }),
|
|
6466
|
+
loading && data.length === 0 && /* @__PURE__ */ jsx("span", { role: "status", className: "sr-only", children: LOADING_LABEL }),
|
|
7342
6467
|
title && /* @__PURE__ */ jsx(TableHeading, { title, description, actions, titleId, descriptionId, inset: true }),
|
|
7343
6468
|
selectable && /* @__PURE__ */ jsx("span", { hidden: true, id: `${headingId}-select-all`, children: "Select all rows shown" }),
|
|
7344
6469
|
selectable && /* @__PURE__ */ jsx("span", { hidden: true, id: `${headingId}-select`, children: "Select" }),
|
|
@@ -8144,6 +7269,12 @@ function WeekView({ date, events, categories, selectedDate, onDayClick, onOpenEv
|
|
|
8144
7269
|
useRevealFocus(allDayRef);
|
|
8145
7270
|
useRevealFocus(scrollerRef);
|
|
8146
7271
|
const { ref: edgesRef, measure: measureEdges, fadeProps: edgeFade } = useScrollEdges();
|
|
7272
|
+
const [dayStrip, setDayStrip] = useState(null);
|
|
7273
|
+
const setDays = useCallback((el) => {
|
|
7274
|
+
edgesRef(el);
|
|
7275
|
+
setDayStrip(el);
|
|
7276
|
+
}, [edgesRef]);
|
|
7277
|
+
useKeyboardScroll(dayStrip, "Days", true, false, "x");
|
|
8147
7278
|
const [list2, setList] = useState(null);
|
|
8148
7279
|
const handleScroll = useCallback((e) => {
|
|
8149
7280
|
if (syncingScroll.current) return;
|
|
@@ -8246,9 +7377,9 @@ function WeekView({ date, events, categories, selectedDate, onDayClick, onOpenEv
|
|
|
8246
7377
|
case "End":
|
|
8247
7378
|
return cellKey(days[days.length - 1], hour);
|
|
8248
7379
|
case "PageUp":
|
|
8249
|
-
return cellKey(
|
|
7380
|
+
return cellKey(addDays(day, -7), hour);
|
|
8250
7381
|
case "PageDown":
|
|
8251
|
-
return cellKey(
|
|
7382
|
+
return cellKey(addDays(day, 7), hour);
|
|
8252
7383
|
default:
|
|
8253
7384
|
return null;
|
|
8254
7385
|
}
|
|
@@ -8268,7 +7399,7 @@ function WeekView({ date, events, categories, selectedDate, onDayClick, onOpenEv
|
|
|
8268
7399
|
return /* @__PURE__ */ jsxs("div", { ref: rootRef, className: "flex flex-col h-full overflow-hidden", onKeyDown: grid.onKeyDown, children: [
|
|
8269
7400
|
/* @__PURE__ */ jsxs("div", { className: "flex border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]", children: [
|
|
8270
7401
|
/* @__PURE__ */ jsx("div", { className: "w-14 shrink-0 border-r-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]" }),
|
|
8271
|
-
/* @__PURE__ */ jsx("div", { ref:
|
|
7402
|
+
/* @__PURE__ */ jsx("div", { ref: setDays, onScroll: measureEdges, ...edgeFade, className: cn("flex-1 overflow-x-auto gs-scrollbar-none", FOCUS_INSET), "data-week-scroll": true, children: /* @__PURE__ */ jsx("div", { className: "grid", style: { gridTemplateColumns: dayGridColumns, minWidth: stripWidth }, children: days.map((day, i) => /* @__PURE__ */ jsxs("div", { className: cn("text-center py-ds-2", i > 0 && "border-l-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]", selectedDate && isSameDay(day, selectedDate) && "bg-[var(--ds-accent-whisper)]"), children: [
|
|
8272
7403
|
/* @__PURE__ */ jsx("div", { className: "text-xs text-[var(--ds-text-muted)] font-medium", children: names[i] }),
|
|
8273
7404
|
/* @__PURE__ */ jsx("div", { className: cn("text-lg font-semibold mt-ds-0.5 mx-auto w-8 h-8 flex items-center justify-center rounded-[var(--ds-radius-full)]", isToday(day) ? TODAY_CIRCLE : "text-[var(--ds-text-primary)]"), children: day.getDate() })
|
|
8274
7405
|
] }, i)) }) })
|
|
@@ -9056,9 +8187,9 @@ function Calendar({
|
|
|
9056
8187
|
return getMonthGrid(currentDate.getFullYear(), currentDate.getMonth(), weekStartsOn)[0][0];
|
|
9057
8188
|
}, [currentView, currentDate, weekStartsOn]);
|
|
9058
8189
|
const drawnTo = useMemo(() => {
|
|
9059
|
-
if (currentView === "week") return
|
|
8190
|
+
if (currentView === "week") return addDays(drawnFrom, 7);
|
|
9060
8191
|
if (currentView === "year") return new Date(drawnFrom.getFullYear() + 1, 0, 1);
|
|
9061
|
-
return
|
|
8192
|
+
return addDays(drawnFrom, 42);
|
|
9062
8193
|
}, [currentView, drawnFrom]);
|
|
9063
8194
|
const { drawnEvents, unreadableRepeats } = useMemo(() => {
|
|
9064
8195
|
const out = [];
|
|
@@ -9096,7 +8227,7 @@ function Calendar({
|
|
|
9096
8227
|
if (currentView === "month") {
|
|
9097
8228
|
setCurrentDate(addMonths(currentDate, direction));
|
|
9098
8229
|
} else if (currentView === "week") {
|
|
9099
|
-
setCurrentDate(
|
|
8230
|
+
setCurrentDate(addDays(currentDate, direction * 7));
|
|
9100
8231
|
} else {
|
|
9101
8232
|
setCurrentDate(new Date(currentDate.getFullYear() + direction, currentDate.getMonth(), 1));
|
|
9102
8233
|
}
|
|
@@ -9956,7 +9087,9 @@ function TreeView({
|
|
|
9956
9087
|
defaultChecked = [],
|
|
9957
9088
|
onSelect,
|
|
9958
9089
|
onCheck,
|
|
9959
|
-
className
|
|
9090
|
+
className,
|
|
9091
|
+
"aria-label": ariaLabel,
|
|
9092
|
+
"aria-labelledby": ariaLabelledBy
|
|
9960
9093
|
}) {
|
|
9961
9094
|
const [ownSelected, setOwnSelected] = useState(() => new Set(defaultSelected));
|
|
9962
9095
|
const selected = useMemo(() => selectedProp ? new Set(selectedProp) : ownSelected, [selectedProp, ownSelected]);
|
|
@@ -10073,7 +9206,7 @@ function TreeView({
|
|
|
10073
9206
|
},
|
|
10074
9207
|
[flatNodes, baseId, expanded, toggleExpand, checkable, handleCheck, selectable, handleSelect]
|
|
10075
9208
|
);
|
|
10076
|
-
return /* @__PURE__ */ jsx("div", { role: "tree", className: cn("text-sm", className), children: nodes.map((node) => /* @__PURE__ */ jsx(
|
|
9209
|
+
return /* @__PURE__ */ jsx("div", { role: "tree", "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, className: cn("text-sm", className), children: nodes.map((node) => /* @__PURE__ */ jsx(
|
|
10077
9210
|
TreeNodeRow,
|
|
10078
9211
|
{
|
|
10079
9212
|
node,
|
|
@@ -10166,6 +9299,7 @@ function TreeNodeRow({
|
|
|
10166
9299
|
CheckboxIndicator2,
|
|
10167
9300
|
{
|
|
10168
9301
|
state: checkState,
|
|
9302
|
+
label: node.label,
|
|
10169
9303
|
onClick: (e) => {
|
|
10170
9304
|
e.stopPropagation();
|
|
10171
9305
|
handleCheck(node);
|
|
@@ -10199,12 +9333,13 @@ function TreeNodeRow({
|
|
|
10199
9333
|
)) })
|
|
10200
9334
|
] });
|
|
10201
9335
|
}
|
|
10202
|
-
function CheckboxIndicator2({ state, onClick }) {
|
|
9336
|
+
function CheckboxIndicator2({ state, label, onClick }) {
|
|
10203
9337
|
const filled = state !== "unchecked";
|
|
10204
9338
|
return /* @__PURE__ */ jsx(
|
|
10205
9339
|
"span",
|
|
10206
9340
|
{
|
|
10207
9341
|
role: "checkbox",
|
|
9342
|
+
"aria-label": label,
|
|
10208
9343
|
"aria-checked": state === "indeterminate" ? "mixed" : state === "checked",
|
|
10209
9344
|
className: cn(
|
|
10210
9345
|
"flex items-center justify-center shrink-0 h-[18px] w-[18px] rounded-[calc(var(--ds-radius-sm)*0.6)] border-[2px] transition-all cursor-pointer",
|
|
@@ -10215,6 +9350,32 @@ function CheckboxIndicator2({ state, onClick }) {
|
|
|
10215
9350
|
}
|
|
10216
9351
|
);
|
|
10217
9352
|
}
|
|
9353
|
+
function useMediaQuery(query) {
|
|
9354
|
+
const subscribe = useCallback((onChange) => {
|
|
9355
|
+
const mql = window.matchMedia(query);
|
|
9356
|
+
mql.addEventListener("change", onChange);
|
|
9357
|
+
return () => mql.removeEventListener("change", onChange);
|
|
9358
|
+
}, [query]);
|
|
9359
|
+
return useSyncExternalStore(
|
|
9360
|
+
subscribe,
|
|
9361
|
+
() => window.matchMedia(query).matches,
|
|
9362
|
+
() => false
|
|
9363
|
+
);
|
|
9364
|
+
}
|
|
9365
|
+
var ROUND_BUTTON = cn(
|
|
9366
|
+
"flex items-center justify-center w-8 h-8",
|
|
9367
|
+
"rounded-[var(--ds-radius-full)]",
|
|
9368
|
+
"bg-[var(--ds-bg-surface-elevated)] border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
9369
|
+
"text-[var(--ds-text-primary)] shadow-[var(--ds-shadow-sm)]",
|
|
9370
|
+
"transition-opacity cursor-pointer hover:bg-[var(--ds-bg-muted)]",
|
|
9371
|
+
FOCUS_RING
|
|
9372
|
+
);
|
|
9373
|
+
var ROTATION_BUTTON = cn(
|
|
9374
|
+
"flex items-center justify-center w-6 h-6 rounded-[var(--ds-radius-full)]",
|
|
9375
|
+
"bg-[color-mix(in_oklab,var(--ds-bg-surface-elevated)_70%,transparent)] [backdrop-filter:blur(6px)] [-webkit-backdrop-filter:blur(6px)]",
|
|
9376
|
+
"text-[var(--ds-text-primary)] transition-colors cursor-pointer hover:bg-[var(--ds-bg-surface-elevated)]",
|
|
9377
|
+
FOCUS_RING
|
|
9378
|
+
);
|
|
10218
9379
|
function Carousel({
|
|
10219
9380
|
children,
|
|
10220
9381
|
autoPlay = false,
|
|
@@ -10222,6 +9383,8 @@ function Carousel({
|
|
|
10222
9383
|
loop = false,
|
|
10223
9384
|
showIndicators = true,
|
|
10224
9385
|
showArrows = true,
|
|
9386
|
+
"aria-label": ariaLabel,
|
|
9387
|
+
"aria-labelledby": ariaLabelledBy,
|
|
10225
9388
|
className,
|
|
10226
9389
|
ref
|
|
10227
9390
|
}) {
|
|
@@ -10230,32 +9393,45 @@ function Carousel({
|
|
|
10230
9393
|
const [dragOffset, setDragOffset] = useState(0);
|
|
10231
9394
|
const trackRef = useRef(null);
|
|
10232
9395
|
const dragStart = useRef(null);
|
|
10233
|
-
const pauseRef = useRef(false);
|
|
10234
9396
|
const count = children.length;
|
|
9397
|
+
const reducedMotion = useMediaQuery("(prefers-reduced-motion: reduce)");
|
|
9398
|
+
const [stopped, setStopped] = useState(null);
|
|
9399
|
+
const playing = autoPlay && count > 1 && !(stopped ?? reducedMotion);
|
|
9400
|
+
const [hovered, setHovered] = useState(false);
|
|
9401
|
+
const [focusInSlide, setFocusInSlide] = useState(false);
|
|
9402
|
+
const rotating = playing && !hovered && !dragging && !focusInSlide;
|
|
9403
|
+
const [said, setSaid] = useState("");
|
|
10235
9404
|
const goTo = useCallback(
|
|
10236
9405
|
(index) => {
|
|
10237
|
-
|
|
10238
|
-
|
|
10239
|
-
}
|
|
10240
|
-
setCurrent(Math.max(0, Math.min(index, count - 1)));
|
|
10241
|
-
}
|
|
9406
|
+
const to = loop ? (index % count + count) % count : Math.max(0, Math.min(index, count - 1));
|
|
9407
|
+
setCurrent(to);
|
|
9408
|
+
setSaid(`Slide ${to + 1} of ${count}`);
|
|
10242
9409
|
},
|
|
10243
9410
|
[count, loop]
|
|
10244
9411
|
);
|
|
10245
9412
|
const next = useCallback(() => goTo(current + 1), [goTo, current]);
|
|
10246
9413
|
const prev = useCallback(() => goTo(current - 1), [goTo, current]);
|
|
10247
9414
|
useEffect(() => {
|
|
10248
|
-
if (!
|
|
10249
|
-
const interval = setInterval(() =>
|
|
10250
|
-
if (!pauseRef.current) goTo(current + 1);
|
|
10251
|
-
}, autoPlayInterval);
|
|
9415
|
+
if (!rotating) return;
|
|
9416
|
+
const interval = setInterval(() => setCurrent((c) => (c + 1) % count), autoPlayInterval);
|
|
10252
9417
|
return () => clearInterval(interval);
|
|
10253
|
-
}, [
|
|
9418
|
+
}, [rotating, autoPlayInterval, count, current]);
|
|
9419
|
+
const onFocus = () => {
|
|
9420
|
+
if (playing && inputModality() !== "pointer") setStopped(true);
|
|
9421
|
+
};
|
|
9422
|
+
const onSlidesBlur = (e) => {
|
|
9423
|
+
if (!e.currentTarget.contains(e.relatedTarget)) setFocusInSlide(false);
|
|
9424
|
+
};
|
|
9425
|
+
const onPointerEnter = (e) => {
|
|
9426
|
+
if (e.pointerType !== "touch") setHovered(true);
|
|
9427
|
+
};
|
|
9428
|
+
const onPointerLeave = (e) => {
|
|
9429
|
+
if (e.pointerType !== "touch") setHovered(false);
|
|
9430
|
+
};
|
|
10254
9431
|
const handlePointerDown = useCallback((e) => {
|
|
10255
9432
|
if (e.pointerType === "mouse" && e.button !== 0) return;
|
|
10256
9433
|
dragStart.current = { x: e.clientX, time: Date.now() };
|
|
10257
9434
|
setDragging(true);
|
|
10258
|
-
pauseRef.current = true;
|
|
10259
9435
|
e.target.setPointerCapture(e.pointerId);
|
|
10260
9436
|
}, []);
|
|
10261
9437
|
const handlePointerMove = useCallback(
|
|
@@ -10280,9 +9456,6 @@ function Carousel({
|
|
|
10280
9456
|
dragStart.current = null;
|
|
10281
9457
|
setDragging(false);
|
|
10282
9458
|
setDragOffset(0);
|
|
10283
|
-
setTimeout(() => {
|
|
10284
|
-
pauseRef.current = false;
|
|
10285
|
-
}, 1e3);
|
|
10286
9459
|
},
|
|
10287
9460
|
[next, prev]
|
|
10288
9461
|
);
|
|
@@ -10293,72 +9466,72 @@ function Carousel({
|
|
|
10293
9466
|
{
|
|
10294
9467
|
ref,
|
|
10295
9468
|
"data-gs-clip": "",
|
|
9469
|
+
role: "group",
|
|
9470
|
+
"aria-roledescription": "carousel",
|
|
9471
|
+
"aria-label": ariaLabel,
|
|
9472
|
+
"aria-labelledby": ariaLabelledBy,
|
|
10296
9473
|
className: cn(
|
|
10297
9474
|
"relative overflow-hidden rounded-[var(--ds-radius-md)]",
|
|
10298
9475
|
"bg-[var(--ds-bg-muted)] border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
10299
9476
|
className
|
|
10300
9477
|
),
|
|
10301
|
-
|
|
10302
|
-
|
|
10303
|
-
|
|
10304
|
-
onMouseLeave: () => {
|
|
10305
|
-
if (!dragging) pauseRef.current = false;
|
|
10306
|
-
},
|
|
9478
|
+
onFocus,
|
|
9479
|
+
onPointerEnter,
|
|
9480
|
+
onPointerLeave,
|
|
10307
9481
|
children: [
|
|
9482
|
+
autoPlay && count > 1 && /* @__PURE__ */ jsx(
|
|
9483
|
+
"button",
|
|
9484
|
+
{
|
|
9485
|
+
type: "button",
|
|
9486
|
+
"data-carousel-rotation": "",
|
|
9487
|
+
onClick: () => setStopped(playing),
|
|
9488
|
+
"aria-label": playing ? "Stop automatic slide show" : "Start automatic slide show",
|
|
9489
|
+
className: cn("absolute left-ds-2 top-ds-2 z-10", ROTATION_BUTTON),
|
|
9490
|
+
children: /* @__PURE__ */ jsx(Icon, { name: playing ? "pause" : "play", size: 12 })
|
|
9491
|
+
}
|
|
9492
|
+
),
|
|
10308
9493
|
/* @__PURE__ */ jsx(
|
|
10309
9494
|
"div",
|
|
10310
9495
|
{
|
|
10311
9496
|
ref: trackRef,
|
|
10312
|
-
className: cn("flex items-stretch", !dragging && "transition-transform duration-400 ease-[var(--ds-transition-ease)]"),
|
|
9497
|
+
className: cn("flex items-stretch", !dragging && "transition-transform duration-400 ease-[var(--ds-transition-ease)] motion-reduce:transition-none"),
|
|
10313
9498
|
style: { transform: `translateX(calc(-${current * 100}% + ${dragOffset}px))` },
|
|
10314
9499
|
onPointerDown: handlePointerDown,
|
|
10315
9500
|
onPointerMove: handlePointerMove,
|
|
10316
9501
|
onPointerUp: handlePointerUp,
|
|
10317
9502
|
onPointerCancel: handlePointerUp,
|
|
10318
|
-
|
|
9503
|
+
onFocus: () => setFocusInSlide(true),
|
|
9504
|
+
onBlur: onSlidesBlur,
|
|
9505
|
+
children: children.map((child, i) => (
|
|
9506
|
+
// each slide named by its place in the set; those out of view are out of reach, for Tab and assistive technology
|
|
9507
|
+
/* @__PURE__ */ jsx("div", { role: "group", "aria-roledescription": "slide", "aria-label": `${i + 1} of ${count}`, inert: i !== current || void 0, className: "w-full shrink-0 select-none flex flex-col [&>*]:flex-1", children: child }, i)
|
|
9508
|
+
))
|
|
10319
9509
|
}
|
|
10320
9510
|
),
|
|
9511
|
+
/* @__PURE__ */ jsx("span", { role: "status", className: "sr-only", children: said }),
|
|
10321
9512
|
showArrows && count > 1 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10322
|
-
/* @__PURE__ */ jsx(
|
|
9513
|
+
/* @__PURE__ */ jsx(AutoTooltip, { content: "Previous slide", children: /* @__PURE__ */ jsx(
|
|
10323
9514
|
"button",
|
|
10324
9515
|
{
|
|
10325
9516
|
type: "button",
|
|
10326
9517
|
onClick: prev,
|
|
10327
9518
|
disabled: !canPrev,
|
|
10328
9519
|
"aria-label": "Previous slide",
|
|
10329
|
-
className: cn(
|
|
10330
|
-
"absolute left-ds-4 top-1/2 -translate-y-1/2 z-10",
|
|
10331
|
-
"flex items-center justify-center w-8 h-8",
|
|
10332
|
-
"rounded-[var(--ds-radius-full)]",
|
|
10333
|
-
"bg-[var(--ds-bg-surface-elevated)] border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
10334
|
-
"text-[var(--ds-text-primary)] shadow-[var(--ds-shadow-sm)]",
|
|
10335
|
-
"transition-opacity cursor-pointer hover:bg-[var(--ds-bg-muted)]",
|
|
10336
|
-
FOCUS_RING,
|
|
10337
|
-
!canPrev && "opacity-0 pointer-events-none"
|
|
10338
|
-
),
|
|
9520
|
+
className: cn("absolute left-ds-4 top-1/2 -translate-y-1/2 z-10", ROUND_BUTTON, !canPrev && "opacity-0 pointer-events-none"),
|
|
10339
9521
|
children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 16, className: "rotate-180" })
|
|
10340
9522
|
}
|
|
10341
|
-
),
|
|
10342
|
-
/* @__PURE__ */ jsx(
|
|
9523
|
+
) }),
|
|
9524
|
+
/* @__PURE__ */ jsx(AutoTooltip, { content: "Next slide", children: /* @__PURE__ */ jsx(
|
|
10343
9525
|
"button",
|
|
10344
9526
|
{
|
|
10345
9527
|
type: "button",
|
|
10346
9528
|
onClick: next,
|
|
10347
9529
|
disabled: !canNext,
|
|
10348
9530
|
"aria-label": "Next slide",
|
|
10349
|
-
className: cn(
|
|
10350
|
-
"absolute right-ds-4 top-1/2 -translate-y-1/2 z-10",
|
|
10351
|
-
"flex items-center justify-center w-8 h-8",
|
|
10352
|
-
"rounded-[var(--ds-radius-full)]",
|
|
10353
|
-
"bg-[var(--ds-bg-surface-elevated)] border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
10354
|
-
"text-[var(--ds-text-primary)] shadow-[var(--ds-shadow-sm)]",
|
|
10355
|
-
"transition-opacity cursor-pointer hover:bg-[var(--ds-bg-muted)]",
|
|
10356
|
-
FOCUS_RING,
|
|
10357
|
-
!canNext && "opacity-0 pointer-events-none"
|
|
10358
|
-
),
|
|
9531
|
+
className: cn("absolute right-ds-4 top-1/2 -translate-y-1/2 z-10", ROUND_BUTTON, !canNext && "opacity-0 pointer-events-none"),
|
|
10359
9532
|
children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 16 })
|
|
10360
9533
|
}
|
|
10361
|
-
)
|
|
9534
|
+
) })
|
|
10362
9535
|
] }),
|
|
10363
9536
|
showIndicators && count > 1 && /* @__PURE__ */ jsx("div", { className: "absolute bottom-ds-3 left-1/2 -translate-x-1/2 flex gap-ds-1.5 z-10", children: children.map((_, i) => /* @__PURE__ */ jsx(
|
|
10364
9537
|
"button",
|
|
@@ -10366,6 +9539,7 @@ function Carousel({
|
|
|
10366
9539
|
type: "button",
|
|
10367
9540
|
onClick: () => goTo(i),
|
|
10368
9541
|
"aria-label": `Go to slide ${i + 1}`,
|
|
9542
|
+
"aria-current": i === current || void 0,
|
|
10369
9543
|
className: cn(
|
|
10370
9544
|
"w-2 h-2 rounded-[var(--ds-radius-full)] transition-all cursor-pointer",
|
|
10371
9545
|
FOCUS_RING,
|
|
@@ -10607,7 +9781,10 @@ function ChatInputBar({ onSend, busy, onStop, onAttach, onVoice, placeholder })
|
|
|
10607
9781
|
) });
|
|
10608
9782
|
}
|
|
10609
9783
|
function Suggestions({ items, onPick, className }) {
|
|
10610
|
-
|
|
9784
|
+
const pressed = useRef(null);
|
|
9785
|
+
return /* @__PURE__ */ jsx("div", { "data-suggestions": "", className: cn("flex flex-wrap gap-ds-2", className), onClickCapture: (e) => {
|
|
9786
|
+
pressed.current = e.target.closest("button");
|
|
9787
|
+
}, children: items.map((s) => /* @__PURE__ */ jsx(Tag, { variant: "default", size: "md", onClick: () => onPick(s, pressed.current), children: s }, s)) });
|
|
10611
9788
|
}
|
|
10612
9789
|
var NEAR_BOTTOM_PX = 24;
|
|
10613
9790
|
function ChatMessageList({
|
|
@@ -10636,7 +9813,7 @@ function ChatMessageList({
|
|
|
10636
9813
|
scrollRef.current = node;
|
|
10637
9814
|
setScroller(node);
|
|
10638
9815
|
}, []);
|
|
10639
|
-
|
|
9816
|
+
useKeyboardScroll(scroller, "Messages");
|
|
10640
9817
|
const atBottomRef = useRef(true);
|
|
10641
9818
|
const [showJump, setShowJump] = useState(false);
|
|
10642
9819
|
const [prevMessages, setPrevMessages] = useState(messages);
|
|
@@ -10675,12 +9852,16 @@ function ChatMessageList({
|
|
|
10675
9852
|
return () => observer.disconnect();
|
|
10676
9853
|
}, [autoScroll, scrollToBottom]);
|
|
10677
9854
|
const empty = messages.length === 0;
|
|
10678
|
-
const
|
|
9855
|
+
const rootRef = useRef(null);
|
|
9856
|
+
const pick = (text, from) => {
|
|
9857
|
+
if (from) focusAfterSelfRemoval(from, { item: from.closest("[data-suggestions]"), to: () => rootRef.current?.querySelector("textarea") });
|
|
9858
|
+
onSend?.(text);
|
|
9859
|
+
};
|
|
10679
9860
|
const showSuggestionsAfterReply = !empty && suggestionsMode === "always" && !!suggestions?.length;
|
|
10680
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col flex-1 min-h-0", className), children: [
|
|
9861
|
+
return /* @__PURE__ */ jsxs("div", { ref: rootRef, className: cn("flex flex-col flex-1 min-h-0", className), children: [
|
|
10681
9862
|
/* @__PURE__ */ jsx("div", { role: "status", "aria-live": "polite", className: "sr-only", children: announcement }),
|
|
10682
9863
|
/* @__PURE__ */ jsxs("div", { className: "relative flex-1 min-h-0", children: [
|
|
10683
|
-
/* @__PURE__ */ jsx("div", { ref: setScroll, onScroll, className: "h-full overflow-y-auto scroll-p-[4px]", children: empty ? /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col items-center justify-center gap-ds-6 px-ds-4 py-ds-8 text-center", children: [
|
|
9864
|
+
/* @__PURE__ */ jsx("div", { ref: setScroll, onScroll, className: cn("h-full overflow-y-auto scroll-p-[4px]", FOCUS_INSET), children: empty ? /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col items-center justify-center gap-ds-6 px-ds-4 py-ds-8 text-center", children: [
|
|
10684
9865
|
emptyState ?? /* @__PURE__ */ jsx(
|
|
10685
9866
|
EmptyState,
|
|
10686
9867
|
{
|
|
@@ -10796,8 +9977,8 @@ function ChatPanel({
|
|
|
10796
9977
|
] });
|
|
10797
9978
|
}
|
|
10798
9979
|
function Sheet({ open, onClose: onCloseProp, title, children, footer, dirty, onDiscard, snapPoints = [0.5, 0.92], container, flush, keepMounted = false, id, labelledBy }) {
|
|
10799
|
-
const { marked, mark } = useOverlayMark(open);
|
|
10800
|
-
const guard = useDirtyGuard(dirty ?? marked, onCloseProp, onDiscard);
|
|
9980
|
+
const { marked, pending, mark } = useOverlayMark(open);
|
|
9981
|
+
const guard = useDirtyGuard((dirty ?? marked) || pending, onCloseProp, onDiscard);
|
|
10801
9982
|
return /* @__PURE__ */ jsx(
|
|
10802
9983
|
DrawerPanel,
|
|
10803
9984
|
{
|
|
@@ -11105,13 +10286,20 @@ var StackedList = forwardRef(function StackedList2({
|
|
|
11105
10286
|
const articles = variant === "articles";
|
|
11106
10287
|
useWholeListCheck("StackedList", items.length, pager);
|
|
11107
10288
|
const shown = pagerPart(items, pager);
|
|
10289
|
+
const listRef = useRef(null);
|
|
10290
|
+
useFocusKeptInList(listRef);
|
|
10291
|
+
const setList = useCallback((node) => {
|
|
10292
|
+
listRef.current = node;
|
|
10293
|
+
if (typeof ref === "function") ref(node);
|
|
10294
|
+
else if (ref) ref.current = node;
|
|
10295
|
+
}, [ref]);
|
|
11108
10296
|
const stackMeta = isPhone && articles;
|
|
11109
10297
|
const selectable = selectedId !== void 0 || items.some((i) => i.selected !== void 0);
|
|
11110
10298
|
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";
|
|
11111
10299
|
const list2 = /* @__PURE__ */ jsx(
|
|
11112
10300
|
"ul",
|
|
11113
10301
|
{
|
|
11114
|
-
ref,
|
|
10302
|
+
ref: setList,
|
|
11115
10303
|
"data-ds-list": "",
|
|
11116
10304
|
className: cn(
|
|
11117
10305
|
divided && "divide-y-[length:var(--ds-border-width)] divide-[var(--ds-border-subtle)]",
|
|
@@ -11221,9 +10409,9 @@ var StackedList = forwardRef(function StackedList2({
|
|
|
11221
10409
|
|
|
11222
10410
|
// ../../showcase/src/lib/time-days.ts
|
|
11223
10411
|
var TIME_ZOOMS = ["day", "week", "month", "quarter"];
|
|
11224
|
-
var
|
|
10412
|
+
var DAY_MS = 864e5;
|
|
11225
10413
|
var DATE_ONLY2 = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
11226
|
-
var utcDay = (y, m, d) => Math.round(Date.UTC(y, m, d) /
|
|
10414
|
+
var utcDay = (y, m, d) => Math.round(Date.UTC(y, m, d) / DAY_MS);
|
|
11227
10415
|
function dayOfDate(d) {
|
|
11228
10416
|
const t = d.getTime();
|
|
11229
10417
|
if (Number.isNaN(t)) return NaN;
|
|
@@ -11232,7 +10420,7 @@ function dayOfDate(d) {
|
|
|
11232
10420
|
first.setHours(0, 0, 0, 0);
|
|
11233
10421
|
if (first.getTime() === t) return day;
|
|
11234
10422
|
const ms = ((d.getHours() * 60 + d.getMinutes()) * 60 + d.getSeconds()) * 1e3 + d.getMilliseconds();
|
|
11235
|
-
return day + ms /
|
|
10423
|
+
return day + ms / DAY_MS;
|
|
11236
10424
|
}
|
|
11237
10425
|
function dayOf(value) {
|
|
11238
10426
|
if (typeof value === "number") return Number.isFinite(value) ? value : NaN;
|
|
@@ -11242,13 +10430,13 @@ function dayOf(value) {
|
|
|
11242
10430
|
if (!m) return dayOfDate(new Date(value));
|
|
11243
10431
|
const [y, mo, d] = [Number(m[1]), Number(m[2]) - 1, Number(m[3])];
|
|
11244
10432
|
const day = utcDay(y, mo, d);
|
|
11245
|
-
const back = new Date(day *
|
|
10433
|
+
const back = new Date(day * DAY_MS);
|
|
11246
10434
|
return back.getUTCFullYear() === y && back.getUTCMonth() === mo && back.getUTCDate() === d ? day : NaN;
|
|
11247
10435
|
}
|
|
11248
10436
|
function dateOfDay(day) {
|
|
11249
10437
|
const whole2 = Math.floor(day);
|
|
11250
|
-
const u = new Date(whole2 *
|
|
11251
|
-
return new Date(u.getUTCFullYear(), u.getUTCMonth(), u.getUTCDate(), 0, 0, 0, Math.round((day - whole2) *
|
|
10438
|
+
const u = new Date(whole2 * DAY_MS);
|
|
10439
|
+
return new Date(u.getUTCFullYear(), u.getUTCMonth(), u.getUTCDate(), 0, 0, 0, Math.round((day - whole2) * DAY_MS));
|
|
11252
10440
|
}
|
|
11253
10441
|
function isZoned(value) {
|
|
11254
10442
|
if (value instanceof Date) return !Number.isNaN(value.getTime());
|
|
@@ -11311,12 +10499,12 @@ function formatDateRange(start, end, words) {
|
|
|
11311
10499
|
if (!Number.isFinite(from) || !Number.isFinite(stop)) return "";
|
|
11312
10500
|
const timed = !isWholeDay(start) || !isWholeDay(until);
|
|
11313
10501
|
const first = timed ? from : Math.floor(from);
|
|
11314
|
-
const
|
|
11315
|
-
const a = new Date(first *
|
|
11316
|
-
const b = new Date(
|
|
10502
|
+
const last = timed ? Math.max(from, stop) : Math.max(first, Math.ceil(stop) - 1);
|
|
10503
|
+
const a = new Date(first * DAY_MS);
|
|
10504
|
+
const b = new Date(last * DAY_MS);
|
|
11317
10505
|
const years = a.getUTCFullYear() !== b.getUTCFullYear() && day.year === void 0;
|
|
11318
10506
|
const f = dayFormatter(locale, { ...day, ...years ? { year: "numeric" } : {}, ...timed ? time : {} });
|
|
11319
|
-
return first ===
|
|
10507
|
+
return first === last ? f.format(a) : range(f, a, b, to ?? (english(f) ? " to " : void 0));
|
|
11320
10508
|
}
|
|
11321
10509
|
|
|
11322
10510
|
// ../../showcase/src/lib/time-scale.ts
|
|
@@ -11327,7 +10515,7 @@ function periodStart(unit, day, weekStartsOn) {
|
|
|
11327
10515
|
const d = Math.floor(day);
|
|
11328
10516
|
if (unit === "day") return d;
|
|
11329
10517
|
if (unit === "week") return d - (weekday(d) - weekStartsOn + 7) % 7;
|
|
11330
|
-
const u = new Date(d *
|
|
10518
|
+
const u = new Date(d * DAY_MS);
|
|
11331
10519
|
const y = u.getUTCFullYear();
|
|
11332
10520
|
const m = u.getUTCMonth();
|
|
11333
10521
|
if (unit === "month") return utcDay(y, m, 1);
|
|
@@ -11337,7 +10525,7 @@ function periodStart(unit, day, weekStartsOn) {
|
|
|
11337
10525
|
function periodAfter(unit, start) {
|
|
11338
10526
|
if (unit === "day") return start + 1;
|
|
11339
10527
|
if (unit === "week") return start + 7;
|
|
11340
|
-
const u = new Date(start *
|
|
10528
|
+
const u = new Date(start * DAY_MS);
|
|
11341
10529
|
const y = u.getUTCFullYear();
|
|
11342
10530
|
const m = u.getUTCMonth();
|
|
11343
10531
|
if (unit === "month") return utcDay(y, m + 1, 1);
|
|
@@ -11345,11 +10533,11 @@ function periodAfter(unit, start) {
|
|
|
11345
10533
|
return utcDay(y + 1, 0, 1);
|
|
11346
10534
|
}
|
|
11347
10535
|
function format2(day, locale, options) {
|
|
11348
|
-
return dayFormatter(locale, options).format(new Date(day *
|
|
10536
|
+
return dayFormatter(locale, options).format(new Date(day * DAY_MS));
|
|
11349
10537
|
}
|
|
11350
10538
|
var pad22 = (n) => String(n).padStart(2, "0");
|
|
11351
10539
|
function keyOf(unit, day) {
|
|
11352
|
-
const u = new Date(day *
|
|
10540
|
+
const u = new Date(day * DAY_MS);
|
|
11353
10541
|
const y = u.getUTCFullYear();
|
|
11354
10542
|
const m = u.getUTCMonth();
|
|
11355
10543
|
if (unit === "year") return String(y);
|
|
@@ -11364,7 +10552,7 @@ function labelsOf(unit, role, day, locale) {
|
|
|
11364
10552
|
else if (unit === "week") forms = [f({ day: "numeric", month: "short" }), f({ day: "numeric" })];
|
|
11365
10553
|
else if (unit === "month") {
|
|
11366
10554
|
forms = role === "major" ? [f({ month: "long", year: "numeric" }), f({ month: "short", year: "numeric" }), f({ month: "short" }), f({ month: "narrow" })] : [f({ month: "long" }), f({ month: "short" }), f({ month: "narrow" })];
|
|
11367
|
-
} else if (unit === "quarter") forms = [`Q${Math.floor(new Date(day *
|
|
10555
|
+
} else if (unit === "quarter") forms = [`Q${Math.floor(new Date(day * DAY_MS).getUTCMonth() / 3) + 1}`];
|
|
11368
10556
|
else forms = [f({ year: "numeric" }), f({ year: "2-digit" })];
|
|
11369
10557
|
return forms;
|
|
11370
10558
|
}
|
|
@@ -11436,8 +10624,8 @@ function scaleOver(from, to, zoom, todayValue, weekStartsOn, locale, pxPerDay, p
|
|
|
11436
10624
|
function extendedEnd(scale, width) {
|
|
11437
10625
|
if (!(width > scale.width) || !(scale.pxPerDay > 0)) return scale.endDay;
|
|
11438
10626
|
const unit = MINOR[scale.zoom];
|
|
11439
|
-
const
|
|
11440
|
-
return periodAfter(unit, periodStart(unit,
|
|
10627
|
+
const last = scale.startDay + Math.ceil(width / scale.pxPerDay) - 1;
|
|
10628
|
+
return periodAfter(unit, periodStart(unit, last, scale.weekStartsOn));
|
|
11441
10629
|
}
|
|
11442
10630
|
function extendTimeScaleTo(scale, endDay) {
|
|
11443
10631
|
if (!(endDay > scale.endDay)) return scale;
|
|
@@ -11896,8 +11084,8 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
11896
11084
|
if (shadeDays && drawn.pxPerDay >= SHADE_MIN) {
|
|
11897
11085
|
for (let d = drawn.startDay; d < drawn.endDay; d++) {
|
|
11898
11086
|
if (!shadeDays(calendarDay(d))) continue;
|
|
11899
|
-
const
|
|
11900
|
-
if (
|
|
11087
|
+
const last = shaded[shaded.length - 1];
|
|
11088
|
+
if (last && Math.abs(last.x + last.width - drawn.x(d)) < 0.5) last.width += drawn.pxPerDay;
|
|
11901
11089
|
else shaded.push({ key: String(d), x: drawn.x(d), width: drawn.pxPerDay });
|
|
11902
11090
|
}
|
|
11903
11091
|
}
|
|
@@ -12004,11 +11192,11 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
12004
11192
|
/* @__PURE__ */ jsx("span", { "aria-live": "polite", className: "min-w-[4.5rem] text-center text-xs text-[var(--ds-text-secondary)]", children: ZOOM_NAMES[scale.zoom] }),
|
|
12005
11193
|
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": "Zoom in", "aria-disabled": !canZoomIn || void 0, className: "aria-disabled:opacity-disabled aria-disabled:cursor-not-allowed", onClick: () => zoom(-1), children: /* @__PURE__ */ jsx(Icon, { name: "plus", size: 14 }) })
|
|
12006
11194
|
] }),
|
|
12007
|
-
/* @__PURE__ */ jsx(
|
|
11195
|
+
/* @__PURE__ */ jsx(PeriodButton, { direction: -1, store, end: Math.max(0, drawn.width - visibleWidth), onPage: (d) => api.page(d) }),
|
|
12008
11196
|
/* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", size: "sm", disabled: todayAtX === null, onClick: () => {
|
|
12009
11197
|
if (todayAtX !== null) setLeft(todayAtX - visibleWidth / 2);
|
|
12010
11198
|
}, children: "Today" }),
|
|
12011
|
-
/* @__PURE__ */ jsx(
|
|
11199
|
+
/* @__PURE__ */ jsx(PeriodButton, { direction: 1, store, end: Math.max(0, drawn.width - visibleWidth), onPage: (d) => api.page(d) }),
|
|
12012
11200
|
toolbar
|
|
12013
11201
|
] })
|
|
12014
11202
|
);
|
|
@@ -12129,6 +11317,13 @@ function TimeBar({ start, end, minWidth = 0, labels, children, className, style,
|
|
|
12129
11317
|
}
|
|
12130
11318
|
);
|
|
12131
11319
|
}
|
|
11320
|
+
function PeriodButton({ direction, store, end, onPage }) {
|
|
11321
|
+
const left = useSyncExternalStore(store.subscribe, () => store.get().scrollLeft, () => 0);
|
|
11322
|
+
const unavailable = direction < 0 ? left <= 0.5 : end > 0 && left >= end - 0.5;
|
|
11323
|
+
return /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": direction < 0 ? "Previous period" : "Next period", "aria-disabled": unavailable || void 0, className: "aria-disabled:opacity-disabled aria-disabled:cursor-not-allowed", onClick: () => {
|
|
11324
|
+
if (!unavailable) onPage(direction);
|
|
11325
|
+
}, children: /* @__PURE__ */ jsx(Icon, { name: direction < 0 ? "chevron-left" : "chevron-right", size: 14 }) });
|
|
11326
|
+
}
|
|
12132
11327
|
function LocaleProvider({ lang, acceptLanguage, children }) {
|
|
12133
11328
|
const value = useMemo(() => localeChoice(lang, acceptLanguage), [lang, acceptLanguage]);
|
|
12134
11329
|
return /* @__PURE__ */ jsx(LocaleContext.Provider, { value, children });
|
|
@@ -12267,7 +11462,7 @@ var NO_DATES = "no dates";
|
|
|
12267
11462
|
var KNOCKOUT = 2;
|
|
12268
11463
|
var EDGE = "border-[length:1px] border-transparent";
|
|
12269
11464
|
var EDGE_WIDTH = 1;
|
|
12270
|
-
var
|
|
11465
|
+
var SELECTED2 = "border-[var(--ds-accent-ink)]";
|
|
12271
11466
|
var UNDATED_INSET = 16;
|
|
12272
11467
|
var NO_GROUPS = [];
|
|
12273
11468
|
var NO_STATUSES = {};
|
|
@@ -12314,7 +11509,7 @@ function NoDates({ cue, selected, className, ...props }) {
|
|
|
12314
11509
|
className: cn(
|
|
12315
11510
|
"sticky flex cursor-pointer items-center gap-ds-1 whitespace-nowrap rounded-[var(--ds-radius-sm)] border-[length:1px] border-dashed border-[var(--ds-border-default)] px-ds-1.5 py-ds-0.5 text-xs text-[var(--ds-text-secondary)]",
|
|
12316
11511
|
FOCUS_RING,
|
|
12317
|
-
selected &&
|
|
11512
|
+
selected && SELECTED2,
|
|
12318
11513
|
className
|
|
12319
11514
|
),
|
|
12320
11515
|
style: { insetInlineStart: labelWidth + UNDATED_INSET },
|
|
@@ -12341,6 +11536,7 @@ function Gantt({
|
|
|
12341
11536
|
describe,
|
|
12342
11537
|
labelHeader = "Task",
|
|
12343
11538
|
toolbar,
|
|
11539
|
+
shadeDays,
|
|
12344
11540
|
"aria-label": ariaLabel,
|
|
12345
11541
|
className
|
|
12346
11542
|
}) {
|
|
@@ -12570,7 +11766,7 @@ function Gantt({
|
|
|
12570
11766
|
] });
|
|
12571
11767
|
const shapeBox = shape.kind === "milestone" ? (
|
|
12572
11768
|
// the diamond draws the target's focus: its outline, which forced colours keep, so the target draws none of its own
|
|
12573
|
-
/* @__PURE__ */ jsx("div", { ...treeitem(row), "aria-selected": isSelected, className: "group absolute grid cursor-pointer place-items-center outline-none", style: { insetInlineStart: (shape.x0 + shape.x1) / 2 - TARGET / 2, top: (ROW_HEIGHT2 - TARGET) / 2, width: TARGET, height: TARGET }, children: /* @__PURE__ */ jsx("span", { "data-gantt-shape": "milestone", "data-item": item.id, className: cn("block rotate-45 rounded-[2px]", GROUP_FOCUS_RING, EDGE, tone.fill, isSelected &&
|
|
11769
|
+
/* @__PURE__ */ jsx("div", { ...treeitem(row), "aria-selected": isSelected, className: "group absolute grid cursor-pointer place-items-center outline-none", style: { insetInlineStart: (shape.x0 + shape.x1) / 2 - TARGET / 2, top: (ROW_HEIGHT2 - TARGET) / 2, width: TARGET, height: TARGET }, children: /* @__PURE__ */ jsx("span", { "data-gantt-shape": "milestone", "data-item": item.id, className: cn("block rotate-45 rounded-[2px]", GROUP_FOCUS_RING, EDGE, tone.fill, isSelected && SELECTED2), style: { width: DIAMOND, height: DIAMOND } }) })
|
|
12574
11770
|
) : (
|
|
12575
11771
|
// TimeBar keeps the title in view beside the pinned column while the bar's start is scrolled away
|
|
12576
11772
|
/* @__PURE__ */ jsx(
|
|
@@ -12583,7 +11779,7 @@ function Gantt({
|
|
|
12583
11779
|
start: dates.start,
|
|
12584
11780
|
end: dates.end,
|
|
12585
11781
|
minWidth: MIN_BAR,
|
|
12586
|
-
className: cn("cursor-pointer text-xs font-medium", EDGE, tone.fill, tone.on, isSelected &&
|
|
11782
|
+
className: cn("cursor-pointer text-xs font-medium", EDGE, tone.fill, tone.on, isSelected && SELECTED2),
|
|
12587
11783
|
style: { top: (ROW_HEIGHT2 - BAR_HEIGHT) / 2, bottom: "auto", height: BAR_HEIGHT },
|
|
12588
11784
|
children: place === "inside" && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", "data-gs-clip": "", className: "flex min-w-0 items-center gap-ds-1 overflow-hidden", children: title })
|
|
12589
11785
|
}
|
|
@@ -12665,6 +11861,7 @@ function Gantt({
|
|
|
12665
11861
|
hasStatuses && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "min-w-0 flex-1" }),
|
|
12666
11862
|
legend
|
|
12667
11863
|
] }),
|
|
11864
|
+
shadeDays,
|
|
12668
11865
|
tabStop: false,
|
|
12669
11866
|
"aria-label": regionLabel,
|
|
12670
11867
|
className: legendApart ? "h-auto flex-1" : className,
|
|
@@ -13011,19 +12208,19 @@ function trackClasses(orientation) {
|
|
|
13011
12208
|
"border-b-[length:var(--ds-nav-h-track-border)] border-[var(--ds-border-default)]"
|
|
13012
12209
|
);
|
|
13013
12210
|
}
|
|
13014
|
-
function useScrollTrack(
|
|
12211
|
+
function useScrollTrack(stopTab, enabled) {
|
|
13015
12212
|
const { ref, elRef, measure, fadeProps } = useScrollEdges({ enabled });
|
|
13016
12213
|
useLayoutEffect(() => {
|
|
13017
12214
|
if (!enabled) return;
|
|
13018
12215
|
const el = elRef.current;
|
|
13019
|
-
const tab = el?.querySelector('[role="tab"][
|
|
12216
|
+
const tab = el?.querySelector('[role="tab"][tabindex="0"]');
|
|
13020
12217
|
if (!el || !tab) return;
|
|
13021
12218
|
const start = tab.offsetLeft;
|
|
13022
12219
|
const end = start + tab.offsetWidth;
|
|
13023
12220
|
if (start < el.scrollLeft + EDGE_FADE) el.scrollLeft = Math.max(0, start - EDGE_FADE);
|
|
13024
12221
|
else if (end > el.scrollLeft + el.clientWidth - EDGE_FADE) el.scrollLeft = end - el.clientWidth + EDGE_FADE;
|
|
13025
12222
|
measure();
|
|
13026
|
-
}, [
|
|
12223
|
+
}, [stopTab, enabled, measure, elRef]);
|
|
13027
12224
|
useEffect(() => {
|
|
13028
12225
|
if (!enabled) return;
|
|
13029
12226
|
const el = elRef.current;
|
|
@@ -13104,7 +12301,7 @@ function getTabsFromDOM(el) {
|
|
|
13104
12301
|
disabled: btn.getAttribute("aria-disabled") === "true"
|
|
13105
12302
|
}));
|
|
13106
12303
|
}
|
|
13107
|
-
function handleTabKeyDown(e, currentId, getTabs, orientation,
|
|
12304
|
+
function handleTabKeyDown(e, currentId, getTabs, orientation, select) {
|
|
13108
12305
|
const prev = orientation === "vertical" ? "ArrowUp" : "ArrowLeft";
|
|
13109
12306
|
const next = orientation === "vertical" ? "ArrowDown" : "ArrowRight";
|
|
13110
12307
|
let targetId;
|
|
@@ -13132,7 +12329,7 @@ function handleTabKeyDown(e, currentId, getTabs, orientation, onTabChange) {
|
|
|
13132
12329
|
}
|
|
13133
12330
|
e.preventDefault();
|
|
13134
12331
|
if (targetId && targetId !== currentId) {
|
|
13135
|
-
|
|
12332
|
+
select?.(targetId);
|
|
13136
12333
|
document.getElementById(`ds-tab-${targetId}`)?.focus();
|
|
13137
12334
|
}
|
|
13138
12335
|
}
|
|
@@ -13149,10 +12346,21 @@ function TabButton({
|
|
|
13149
12346
|
truncate,
|
|
13150
12347
|
onKeyDown,
|
|
13151
12348
|
className,
|
|
13152
|
-
hasPanel
|
|
12349
|
+
hasPanel,
|
|
12350
|
+
isTabStop,
|
|
12351
|
+
setFocusedTab
|
|
13153
12352
|
}) {
|
|
13154
12353
|
const { ref: truncRef, isTruncated } = useTextOverflow({ lines: 1, disabled: !truncate && orientation !== "horizontal" });
|
|
13155
12354
|
const isActive2 = activeTab === id;
|
|
12355
|
+
const forget = useCallback(() => setFocusedTab((f) => f === id ? null : f), [setFocusedTab, id]);
|
|
12356
|
+
useEffect(() => forget, [forget]);
|
|
12357
|
+
const focusTracking = {
|
|
12358
|
+
tabIndex: isTabStop ? 0 : -1,
|
|
12359
|
+
onFocus: () => setFocusedTab(id),
|
|
12360
|
+
onBlur: (e) => {
|
|
12361
|
+
if (!e.currentTarget.closest('[role="tablist"]')?.contains(e.relatedTarget)) forget();
|
|
12362
|
+
}
|
|
12363
|
+
};
|
|
13156
12364
|
const tabId = `ds-tab-${id}`;
|
|
13157
12365
|
const panelId = hasPanel === false ? void 0 : `ds-tabpanel-${id}`;
|
|
13158
12366
|
const badgeBg = orientation === "vertical" ? "bg-[var(--ds-nav-v-badge-bg)]" : "bg-[var(--ds-nav-h-badge-bg)]";
|
|
@@ -13171,7 +12379,7 @@ function TabButton({
|
|
|
13171
12379
|
"aria-selected": isActive2,
|
|
13172
12380
|
"aria-controls": panelId,
|
|
13173
12381
|
"aria-disabled": disabled || void 0,
|
|
13174
|
-
|
|
12382
|
+
...focusTracking,
|
|
13175
12383
|
onClick: disabled ? void 0 : () => onTabChange(id),
|
|
13176
12384
|
onKeyDown,
|
|
13177
12385
|
className: cn(
|
|
@@ -13207,7 +12415,7 @@ function TabButton({
|
|
|
13207
12415
|
"aria-selected": isActive2,
|
|
13208
12416
|
"aria-controls": panelId,
|
|
13209
12417
|
"aria-disabled": disabled || void 0,
|
|
13210
|
-
|
|
12418
|
+
...focusTracking,
|
|
13211
12419
|
onClick: disabled ? void 0 : () => onTabChange(id),
|
|
13212
12420
|
onKeyDown,
|
|
13213
12421
|
className: cn(
|
|
@@ -13242,8 +12450,8 @@ function TabButton({
|
|
|
13242
12450
|
return btn;
|
|
13243
12451
|
}
|
|
13244
12452
|
function TabsList({ children, className }) {
|
|
13245
|
-
const { orientation, fullWidth, overflow,
|
|
13246
|
-
const track = useScrollTrack(
|
|
12453
|
+
const { orientation, fullWidth, overflow, stopTab } = useTabsCtx();
|
|
12454
|
+
const track = useScrollTrack(stopTab, orientation === "horizontal" && overflow === "scroll");
|
|
13247
12455
|
if (orientation === "vertical") {
|
|
13248
12456
|
return /* @__PURE__ */ jsx(
|
|
13249
12457
|
"div",
|
|
@@ -13258,7 +12466,7 @@ function TabsList({ children, className }) {
|
|
|
13258
12466
|
return /* @__PURE__ */ jsx(TabStrip, { overflow, fullWidth, track, className, children });
|
|
13259
12467
|
}
|
|
13260
12468
|
function TabsTrigger({ value, children, count, icon, disabled, truncate, className }) {
|
|
13261
|
-
const { activeTab, onTabChange, orientation, fullWidth, overflow } = useTabsCtx();
|
|
12469
|
+
const { activeTab, onTabChange, orientation, fullWidth, overflow, activation, stopTab, setFocusedTab } = useTabsCtx();
|
|
13262
12470
|
return /* @__PURE__ */ jsx(
|
|
13263
12471
|
TabButton,
|
|
13264
12472
|
{
|
|
@@ -13272,7 +12480,9 @@ function TabsTrigger({ value, children, count, icon, disabled, truncate, classNa
|
|
|
13272
12480
|
activeTab,
|
|
13273
12481
|
onTabChange,
|
|
13274
12482
|
fullWidth,
|
|
13275
|
-
|
|
12483
|
+
isTabStop: value === stopTab,
|
|
12484
|
+
setFocusedTab,
|
|
12485
|
+
onKeyDown: (e) => handleTabKeyDown(e, value, () => getTabsFromDOM(e.currentTarget), orientation, activation === "automatic" ? onTabChange : void 0),
|
|
13276
12486
|
className
|
|
13277
12487
|
}
|
|
13278
12488
|
);
|
|
@@ -13299,15 +12509,20 @@ function TabsRoot(props) {
|
|
|
13299
12509
|
orientation = "horizontal",
|
|
13300
12510
|
fullWidth = false,
|
|
13301
12511
|
overflow = "scroll",
|
|
12512
|
+
activation = "automatic",
|
|
13302
12513
|
className
|
|
13303
12514
|
} = props;
|
|
13304
12515
|
const isMobile = useBreakpoint("md");
|
|
13305
12516
|
const effectiveOrientation = orientation === "responsive" ? "vertical" : orientation;
|
|
13306
12517
|
const arrayApi = "tabs" in props && !!props.tabs;
|
|
13307
12518
|
const arrayOverflow = arrayApi && props.tabs.some((t) => t.truncate) ? "truncate" : overflow;
|
|
13308
|
-
const
|
|
12519
|
+
const [focusedTab, setFocusedTab] = useState(null);
|
|
12520
|
+
const stopTab = focusedTab ?? activeTab;
|
|
12521
|
+
const track = useScrollTrack(stopTab, arrayApi && effectiveOrientation === "horizontal" && arrayOverflow === "scroll");
|
|
13309
12522
|
if ("tabs" in props && props.tabs) {
|
|
13310
12523
|
const { tabs, mobile = "scroll" } = props;
|
|
12524
|
+
const stopIndex = rovingTabStop(tabs, (t) => t.id === stopTab, (t) => !!t.disabled && t.id !== stopTab);
|
|
12525
|
+
const select = activation === "automatic" ? onTabChange : void 0;
|
|
13311
12526
|
const collapseToDropdown = isMobile && (orientation === "responsive" || mobile === "dropdown");
|
|
13312
12527
|
if (collapseToDropdown) {
|
|
13313
12528
|
return (
|
|
@@ -13342,14 +12557,14 @@ function TabsRoot(props) {
|
|
|
13342
12557
|
children: tab.group
|
|
13343
12558
|
}
|
|
13344
12559
|
),
|
|
13345
|
-
/* @__PURE__ */ jsx(TabButton, { hasPanel: false, ...tab, orientation: effectiveOrientation, activeTab, onTabChange, fullWidth, onKeyDown: (e) => handleTabKeyDown(e, tab.id, () => tabs, effectiveOrientation,
|
|
12560
|
+
/* @__PURE__ */ jsx(TabButton, { hasPanel: false, ...tab, orientation: effectiveOrientation, activeTab, onTabChange, fullWidth, isTabStop: i === stopIndex, setFocusedTab, onKeyDown: (e) => handleTabKeyDown(e, tab.id, () => tabs, effectiveOrientation, select) })
|
|
13346
12561
|
] }, tab.id))
|
|
13347
12562
|
}
|
|
13348
12563
|
);
|
|
13349
12564
|
}
|
|
13350
|
-
return /* @__PURE__ */ jsx(TabStrip, { overflow: arrayOverflow, fullWidth, track, className, children: tabs.map((tab) => /* @__PURE__ */ jsx(TabButton, { hasPanel: false, ...tab, orientation: effectiveOrientation, activeTab, onTabChange, fullWidth, onKeyDown: (e) => handleTabKeyDown(e, tab.id, () => tabs, effectiveOrientation,
|
|
12565
|
+
return /* @__PURE__ */ jsx(TabStrip, { overflow: arrayOverflow, fullWidth, track, className, children: tabs.map((tab, i) => /* @__PURE__ */ jsx(TabButton, { hasPanel: false, ...tab, orientation: effectiveOrientation, activeTab, onTabChange, fullWidth, isTabStop: i === stopIndex, setFocusedTab, onKeyDown: (e) => handleTabKeyDown(e, tab.id, () => tabs, effectiveOrientation, select) }, tab.id)) });
|
|
13351
12566
|
}
|
|
13352
|
-
return /* @__PURE__ */ jsx(TabsContext.Provider, { value: { activeTab, onTabChange, orientation: effectiveOrientation, fullWidth, overflow }, children: /* @__PURE__ */ jsx("div", { className, children: props.children }) });
|
|
12567
|
+
return /* @__PURE__ */ jsx(TabsContext.Provider, { value: { activeTab, onTabChange, orientation: effectiveOrientation, fullWidth, overflow, activation, stopTab, setFocusedTab }, children: /* @__PURE__ */ jsx("div", { className, children: props.children }) });
|
|
13353
12568
|
}
|
|
13354
12569
|
var Tabs = Object.assign(TabsRoot, {
|
|
13355
12570
|
List: TabsList,
|
|
@@ -13900,7 +13115,7 @@ var Sidebar = forwardRef(function Sidebar2({
|
|
|
13900
13115
|
]
|
|
13901
13116
|
}
|
|
13902
13117
|
);
|
|
13903
|
-
return
|
|
13118
|
+
return /* @__PURE__ */ jsx(AutoTooltip, { content: "Expand sidebar", side: "right", delay: 100, container: portalEl ?? void 0, disabled: !collapsed, children: collapseButton });
|
|
13904
13119
|
})(),
|
|
13905
13120
|
footer && /* @__PURE__ */ jsx(
|
|
13906
13121
|
"div",
|
|
@@ -14151,6 +13366,8 @@ function SidebarNav({
|
|
|
14151
13366
|
item.onClick?.();
|
|
14152
13367
|
onItemClick?.(item, index);
|
|
14153
13368
|
},
|
|
13369
|
+
"aria-label": collapsed && isRoot ? item.label : void 0,
|
|
13370
|
+
"aria-current": item.active ? "page" : void 0,
|
|
14154
13371
|
className: cn(
|
|
14155
13372
|
"flex items-center gap-ds-2 transition-colors cursor-pointer",
|
|
14156
13373
|
FOCUS_RING,
|
|
@@ -14331,7 +13548,7 @@ function SidebarNav({
|
|
|
14331
13548
|
{
|
|
14332
13549
|
className: cn("flex flex-col", className),
|
|
14333
13550
|
style: {
|
|
14334
|
-
paddingTop: isCompact ? "var(--ds-space-1)" : dropTopInset ?
|
|
13551
|
+
paddingTop: isCompact ? "var(--ds-space-1)" : dropTopInset ? `${FOCUS_ROOM}px` : "var(--ds-space-3)",
|
|
14335
13552
|
paddingRight: isCompact ? "var(--ds-space-1)" : "var(--ds-space-2)",
|
|
14336
13553
|
paddingBottom: isCompact ? "var(--ds-space-1)" : "var(--ds-space-3)",
|
|
14337
13554
|
paddingLeft: isCompact ? "var(--ds-space-1)" : "var(--ds-space-2)",
|
|
@@ -15105,6 +14322,7 @@ function BottomNav({ items, onItemClick, maxVisible = 5, className, ref }) {
|
|
|
15105
14322
|
{
|
|
15106
14323
|
type: "button",
|
|
15107
14324
|
role: "menuitem",
|
|
14325
|
+
"aria-current": item.active ? "page" : void 0,
|
|
15108
14326
|
onClick: () => {
|
|
15109
14327
|
onItemClick?.(item, maxVisible - 1 + i);
|
|
15110
14328
|
closeOverflow();
|
|
@@ -15132,26 +14350,74 @@ function BottomNav({ items, onItemClick, maxVisible = 5, className, ref }) {
|
|
|
15132
14350
|
);
|
|
15133
14351
|
}
|
|
15134
14352
|
function NavButton({ item, onClick }) {
|
|
15135
|
-
return
|
|
15136
|
-
|
|
15137
|
-
|
|
15138
|
-
|
|
15139
|
-
|
|
15140
|
-
|
|
15141
|
-
|
|
15142
|
-
"
|
|
15143
|
-
|
|
15144
|
-
|
|
15145
|
-
|
|
15146
|
-
|
|
15147
|
-
|
|
15148
|
-
|
|
15149
|
-
|
|
15150
|
-
|
|
15151
|
-
|
|
14353
|
+
return (
|
|
14354
|
+
// the current page says so, not by its colour alone (Sprint 25.29 item 17)
|
|
14355
|
+
/* @__PURE__ */ jsxs(
|
|
14356
|
+
"button",
|
|
14357
|
+
{
|
|
14358
|
+
type: "button",
|
|
14359
|
+
onClick,
|
|
14360
|
+
"aria-current": item.active ? "page" : void 0,
|
|
14361
|
+
className: cn(
|
|
14362
|
+
"flex flex-col items-center justify-center gap-ds-0.5 flex-1 h-full",
|
|
14363
|
+
"text-2xs font-medium transition-colors cursor-pointer",
|
|
14364
|
+
// flush with the window's edge (the bar's foot and its ends): the outline sits inside, where it shows whole (D8)
|
|
14365
|
+
FOCUS_INSET,
|
|
14366
|
+
item.active ? "text-[var(--ds-accent-ink)]" : "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)]"
|
|
14367
|
+
),
|
|
14368
|
+
children: [
|
|
14369
|
+
/* @__PURE__ */ jsx(Icon, { name: item.icon, size: 20 }),
|
|
14370
|
+
/* @__PURE__ */ jsx("span", { children: item.label })
|
|
14371
|
+
]
|
|
14372
|
+
}
|
|
14373
|
+
)
|
|
15152
14374
|
);
|
|
15153
14375
|
}
|
|
15154
14376
|
|
|
14377
|
+
// ../../showcase/src/lib/scroll-padding.ts
|
|
14378
|
+
var registry = /* @__PURE__ */ new WeakMap();
|
|
14379
|
+
function apply(scroller, claims) {
|
|
14380
|
+
const px = Math.max(0, ...claims.sizes.values());
|
|
14381
|
+
if (px) {
|
|
14382
|
+
scroller.style.setProperty("scroll-padding-top", claims.floor ? `max(${claims.floor}, ${px}px)` : `${px}px`);
|
|
14383
|
+
return;
|
|
14384
|
+
}
|
|
14385
|
+
if (claims.inline) scroller.style.setProperty("scroll-padding-top", claims.inline, claims.priority);
|
|
14386
|
+
else scroller.style.removeProperty("scroll-padding-top");
|
|
14387
|
+
}
|
|
14388
|
+
function claimScrollPaddingTop(scroller) {
|
|
14389
|
+
let claims = registry.get(scroller);
|
|
14390
|
+
if (!claims) {
|
|
14391
|
+
const own = getComputedStyle(scroller).getPropertyValue("scroll-padding-top").trim();
|
|
14392
|
+
claims = {
|
|
14393
|
+
inline: scroller.style.getPropertyValue("scroll-padding-top"),
|
|
14394
|
+
priority: scroller.style.getPropertyPriority("scroll-padding-top"),
|
|
14395
|
+
floor: own && own !== "auto" && parseFloat(own) !== 0 ? own : null,
|
|
14396
|
+
sizes: /* @__PURE__ */ new Map(),
|
|
14397
|
+
holders: 0
|
|
14398
|
+
};
|
|
14399
|
+
registry.set(scroller, claims);
|
|
14400
|
+
}
|
|
14401
|
+
const held = claims;
|
|
14402
|
+
held.holders++;
|
|
14403
|
+
const token = /* @__PURE__ */ Symbol("scroll-padding-claim");
|
|
14404
|
+
let released = false;
|
|
14405
|
+
return {
|
|
14406
|
+
set(px) {
|
|
14407
|
+
if (released) return;
|
|
14408
|
+
held.sizes.set(token, Math.max(0, Math.ceil(px)));
|
|
14409
|
+
apply(scroller, held);
|
|
14410
|
+
},
|
|
14411
|
+
release() {
|
|
14412
|
+
if (released) return;
|
|
14413
|
+
released = true;
|
|
14414
|
+
held.sizes.delete(token);
|
|
14415
|
+
apply(scroller, held);
|
|
14416
|
+
if (--held.holders === 0) registry.delete(scroller);
|
|
14417
|
+
}
|
|
14418
|
+
};
|
|
14419
|
+
}
|
|
14420
|
+
|
|
15155
14421
|
// ../../showcase/src/lib/shell-theme.ts
|
|
15156
14422
|
var PAGE_HEADER_MARK = /* @__PURE__ */ Symbol.for("gridsmith.PageHeader");
|
|
15157
14423
|
function resolvePageHeader(theme, props, facts) {
|
|
@@ -16075,20 +15341,38 @@ function SnappingHeader({
|
|
|
16075
15341
|
} : setStickyRef;
|
|
16076
15342
|
useLayoutEffect(() => {
|
|
16077
15343
|
const report = container?.setPinnedHeight;
|
|
16078
|
-
if (!report) return;
|
|
16079
15344
|
const el = stickyRef.current;
|
|
16080
15345
|
if (!(pinned && collapsed) || !el) {
|
|
16081
|
-
report(null);
|
|
15346
|
+
report?.(null);
|
|
16082
15347
|
return;
|
|
16083
15348
|
}
|
|
16084
|
-
const
|
|
15349
|
+
const doc = el.ownerDocument;
|
|
15350
|
+
const claim = claimScrollPaddingTop(findScrollParent(el) ?? doc.documentElement);
|
|
15351
|
+
let inBar = el.contains(doc.activeElement);
|
|
15352
|
+
const sync = () => {
|
|
15353
|
+
report?.(el.offsetHeight);
|
|
15354
|
+
claim.set(inBar ? 0 : (parseFloat(getComputedStyle(el).top) || 0) + el.offsetHeight + FOCUS_ROOM);
|
|
15355
|
+
};
|
|
15356
|
+
const follow2 = (to) => {
|
|
15357
|
+
const now = to instanceof Node && el.contains(to);
|
|
15358
|
+
if (now !== inBar) {
|
|
15359
|
+
inBar = now;
|
|
15360
|
+
sync();
|
|
15361
|
+
}
|
|
15362
|
+
};
|
|
15363
|
+
const onFocusIn = (e) => follow2(e.target);
|
|
15364
|
+
const onFocusOut = (e) => follow2(e.relatedTarget);
|
|
16085
15365
|
sync();
|
|
16086
|
-
|
|
16087
|
-
|
|
16088
|
-
obs
|
|
15366
|
+
doc.addEventListener("focusin", onFocusIn, true);
|
|
15367
|
+
doc.addEventListener("focusout", onFocusOut, true);
|
|
15368
|
+
const obs = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(sync);
|
|
15369
|
+
obs?.observe(el);
|
|
16089
15370
|
return () => {
|
|
16090
|
-
obs
|
|
16091
|
-
|
|
15371
|
+
obs?.disconnect();
|
|
15372
|
+
doc.removeEventListener("focusin", onFocusIn, true);
|
|
15373
|
+
doc.removeEventListener("focusout", onFocusOut, true);
|
|
15374
|
+
report?.(null);
|
|
15375
|
+
claim.release();
|
|
16092
15376
|
};
|
|
16093
15377
|
}, [container?.setPinnedHeight, pinned, collapsed]);
|
|
16094
15378
|
const sentinelRef = useRef(null);
|
|
@@ -17345,68 +16629,6 @@ function CommandPalette({ open, onOpenChange, commands, placeholder = "Type a co
|
|
|
17345
16629
|
container ?? document.body
|
|
17346
16630
|
);
|
|
17347
16631
|
}
|
|
17348
|
-
function HoverCard({
|
|
17349
|
-
content,
|
|
17350
|
-
children,
|
|
17351
|
-
side = "bottom",
|
|
17352
|
-
delay = 300,
|
|
17353
|
-
closeDelay = 200,
|
|
17354
|
-
className,
|
|
17355
|
-
container
|
|
17356
|
-
}) {
|
|
17357
|
-
const [open, setOpen] = useState(false);
|
|
17358
|
-
const triggerRef = useRef(null);
|
|
17359
|
-
const floatingRef = useRef(null);
|
|
17360
|
-
const openTimeout = useRef(void 0);
|
|
17361
|
-
const closeTimeout = useRef(void 0);
|
|
17362
|
-
const pos = usePosition(triggerRef, floatingRef, open, { side, offset: 8, flip: true });
|
|
17363
|
-
const show = useCallback(() => {
|
|
17364
|
-
clearTimeout(closeTimeout.current);
|
|
17365
|
-
openTimeout.current = setTimeout(() => setOpen(true), delay);
|
|
17366
|
-
}, [delay]);
|
|
17367
|
-
const hide = useCallback(() => {
|
|
17368
|
-
clearTimeout(openTimeout.current);
|
|
17369
|
-
closeTimeout.current = setTimeout(() => setOpen(false), closeDelay);
|
|
17370
|
-
}, [closeDelay]);
|
|
17371
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
17372
|
-
/* @__PURE__ */ jsx(
|
|
17373
|
-
Slot,
|
|
17374
|
-
{
|
|
17375
|
-
ref: triggerRef,
|
|
17376
|
-
onMouseEnter: show,
|
|
17377
|
-
onMouseLeave: hide,
|
|
17378
|
-
onFocus: show,
|
|
17379
|
-
onBlur: hide,
|
|
17380
|
-
children
|
|
17381
|
-
}
|
|
17382
|
-
),
|
|
17383
|
-
open && createPortal(
|
|
17384
|
-
/* @__PURE__ */ jsx(
|
|
17385
|
-
"div",
|
|
17386
|
-
{
|
|
17387
|
-
ref: floatingRef,
|
|
17388
|
-
onMouseEnter: () => {
|
|
17389
|
-
clearTimeout(closeTimeout.current);
|
|
17390
|
-
},
|
|
17391
|
-
onMouseLeave: hide,
|
|
17392
|
-
className: cn(
|
|
17393
|
-
"fixed z-[var(--ds-z-popover)]",
|
|
17394
|
-
"w-72 p-ds-4",
|
|
17395
|
-
"bg-[var(--ds-bg-surface-elevated)] text-[var(--ds-text-primary)]",
|
|
17396
|
-
GLASS_DROPDOWN,
|
|
17397
|
-
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
17398
|
-
"rounded-[var(--ds-radius-md)]",
|
|
17399
|
-
"animate-in fade-in-0 zoom-in-95",
|
|
17400
|
-
className
|
|
17401
|
-
),
|
|
17402
|
-
style: { top: pos.top, left: pos.left },
|
|
17403
|
-
children: /* @__PURE__ */ jsx(RowsCtx, { value: false, children: content })
|
|
17404
|
-
}
|
|
17405
|
-
),
|
|
17406
|
-
container ?? document.body
|
|
17407
|
-
)
|
|
17408
|
-
] });
|
|
17409
|
-
}
|
|
17410
16632
|
function ContextMenu({ items, children, className, ref, container }) {
|
|
17411
16633
|
const [open, setOpen] = useState(false);
|
|
17412
16634
|
const [pos, setPos] = useState({ x: 0, y: 0 });
|
|
@@ -17611,7 +16833,8 @@ function NotificationCenter({
|
|
|
17611
16833
|
document.removeEventListener("mousedown", onClick);
|
|
17612
16834
|
};
|
|
17613
16835
|
}, [open, setOpen, isTopLayer, returnFocus]);
|
|
17614
|
-
const
|
|
16836
|
+
const today = useCurrentDay();
|
|
16837
|
+
const grouped = groupByDay(filteredNotifications, today);
|
|
17615
16838
|
if (variant === "page") {
|
|
17616
16839
|
return /* @__PURE__ */ jsxs("div", { ref, className: cn("w-full", className), children: [
|
|
17617
16840
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-ds-4", children: [
|
|
@@ -17661,8 +16884,8 @@ function NotificationCenter({
|
|
|
17661
16884
|
/* @__PURE__ */ jsx(Icon, { name: "bell", size: 32, className: "opacity-30 mb-ds-2" }),
|
|
17662
16885
|
/* @__PURE__ */ jsx("p", { className: "text-sm", children: filter === "unread" ? "No unread notifications" : "No notifications" })
|
|
17663
16886
|
] }),
|
|
17664
|
-
grouped.map(({ label, items }) => /* @__PURE__ */ jsxs("div", { className: "mb-ds-2", children: [
|
|
17665
|
-
/* @__PURE__ */ jsx("p", { className: "px-ds-1 pt-ds-3 pb-ds-1 text-2xs font-medium uppercase tracking-wider text-[var(--ds-text-muted)]", children: label }),
|
|
16887
|
+
/* @__PURE__ */ jsx(RowsCtx, { value: true, children: grouped.map(({ label, items }) => /* @__PURE__ */ jsxs("div", { className: "mb-ds-2", children: [
|
|
16888
|
+
label && /* @__PURE__ */ jsx("p", { className: "px-ds-1 pt-ds-3 pb-ds-1 text-2xs font-medium uppercase tracking-wider text-[var(--ds-text-muted)]", children: label }),
|
|
17666
16889
|
items.map((n) => /* @__PURE__ */ jsxs(
|
|
17667
16890
|
"div",
|
|
17668
16891
|
{
|
|
@@ -17688,7 +16911,7 @@ function NotificationCenter({
|
|
|
17688
16911
|
/* @__PURE__ */ jsx(TruncTitle, { children: n.title })
|
|
17689
16912
|
] }),
|
|
17690
16913
|
n.description && /* @__PURE__ */ jsx(ClampedDesc, { className: "text-xs text-[var(--ds-text-muted)] mt-ds-0.5", children: n.description }),
|
|
17691
|
-
/* @__PURE__ */ jsx(
|
|
16914
|
+
/* @__PURE__ */ jsx(NotificationTime, { timestamp: n.timestamp })
|
|
17692
16915
|
] }),
|
|
17693
16916
|
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-ds-1 shrink-0", children: [
|
|
17694
16917
|
!n.read && onMarkRead && /* @__PURE__ */ jsx(
|
|
@@ -17716,7 +16939,7 @@ function NotificationCenter({
|
|
|
17716
16939
|
},
|
|
17717
16940
|
n.id
|
|
17718
16941
|
))
|
|
17719
|
-
] }, label))
|
|
16942
|
+
] }, label ?? "rows")) })
|
|
17720
16943
|
] });
|
|
17721
16944
|
}
|
|
17722
16945
|
return /* @__PURE__ */ jsxs("div", { ref, className: cn("relative inline-flex", className), children: [
|
|
@@ -17775,8 +16998,8 @@ function NotificationCenter({
|
|
|
17775
16998
|
/* @__PURE__ */ jsx(Icon, { name: "bell", size: 32, className: "opacity-30 mb-ds-2" }),
|
|
17776
16999
|
/* @__PURE__ */ jsx("p", { className: "text-sm", children: "No notifications" })
|
|
17777
17000
|
] }),
|
|
17778
|
-
grouped.map(({ label, items }) => /* @__PURE__ */ jsxs("div", { children: [
|
|
17779
|
-
/* @__PURE__ */ jsx("p", { className: "px-ds-4 pt-ds-3 pb-ds-1 text-2xs font-medium uppercase tracking-wider text-[var(--ds-text-muted)]", children: label }),
|
|
17001
|
+
/* @__PURE__ */ jsx(RowsCtx, { value: true, children: grouped.map(({ label, items }) => /* @__PURE__ */ jsxs("div", { children: [
|
|
17002
|
+
label && /* @__PURE__ */ jsx("p", { className: "px-ds-4 pt-ds-3 pb-ds-1 text-2xs font-medium uppercase tracking-wider text-[var(--ds-text-muted)]", children: label }),
|
|
17780
17003
|
items.map((n) => /* @__PURE__ */ jsxs(
|
|
17781
17004
|
"div",
|
|
17782
17005
|
{
|
|
@@ -17802,7 +17025,7 @@ function NotificationCenter({
|
|
|
17802
17025
|
/* @__PURE__ */ jsx(TruncTitle, { children: n.title })
|
|
17803
17026
|
] }),
|
|
17804
17027
|
n.description && /* @__PURE__ */ jsx(ClampedDesc, { className: "text-xs text-[var(--ds-text-muted)] mt-ds-0.5", children: n.description }),
|
|
17805
|
-
/* @__PURE__ */ jsx(
|
|
17028
|
+
/* @__PURE__ */ jsx(NotificationTime, { timestamp: n.timestamp })
|
|
17806
17029
|
] }),
|
|
17807
17030
|
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-ds-1 shrink-0", children: [
|
|
17808
17031
|
!n.read && onMarkRead && /* @__PURE__ */ jsx(
|
|
@@ -17830,7 +17053,7 @@ function NotificationCenter({
|
|
|
17830
17053
|
},
|
|
17831
17054
|
n.id
|
|
17832
17055
|
))
|
|
17833
|
-
] }, label))
|
|
17056
|
+
] }, label ?? "rows")) })
|
|
17834
17057
|
] })
|
|
17835
17058
|
]
|
|
17836
17059
|
}
|
|
@@ -17839,27 +17062,33 @@ function NotificationCenter({
|
|
|
17839
17062
|
)
|
|
17840
17063
|
] });
|
|
17841
17064
|
}
|
|
17842
|
-
function
|
|
17843
|
-
const
|
|
17844
|
-
|
|
17845
|
-
|
|
17846
|
-
|
|
17847
|
-
const
|
|
17848
|
-
const
|
|
17065
|
+
function NotificationTime({ timestamp }) {
|
|
17066
|
+
const at = datedMillis(timestamp);
|
|
17067
|
+
return /* @__PURE__ */ jsx("p", { className: "text-2xs text-[var(--ds-text-muted)] mt-ds-1 tabular-nums", children: typeof timestamp === "string" && !Number.isFinite(at) ? timestamp : /* @__PURE__ */ jsx(RelativeTime, { time: at }) });
|
|
17068
|
+
}
|
|
17069
|
+
function useCurrentDay() {
|
|
17070
|
+
const today = useToday();
|
|
17071
|
+
const [redraws, redraw] = useReducer((n) => n + 1, 0);
|
|
17072
|
+
const tomorrow = today && new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1).getTime();
|
|
17073
|
+
useEffect(() => {
|
|
17074
|
+
if (tomorrow === null) return;
|
|
17075
|
+
const timer = setTimeout(redraw, tomorrow - Date.now() + 1e3);
|
|
17076
|
+
return () => clearTimeout(timer);
|
|
17077
|
+
}, [tomorrow, redraws]);
|
|
17078
|
+
return today;
|
|
17079
|
+
}
|
|
17080
|
+
var DAY_GROUPS = ["Today", "Yesterday", "Earlier"];
|
|
17081
|
+
function groupByDay(notifications, today) {
|
|
17082
|
+
if (!today) return notifications.length ? [{ label: null, items: notifications }] : [];
|
|
17083
|
+
const todayStarts = new Date(today.getFullYear(), today.getMonth(), today.getDate()).getTime();
|
|
17084
|
+
const yesterdayStarts = new Date(today.getFullYear(), today.getMonth(), today.getDate() - 1).getTime();
|
|
17085
|
+
const groups = new Map(DAY_GROUPS.map((label) => [label, []]));
|
|
17849
17086
|
for (const n of notifications) {
|
|
17850
|
-
|
|
17851
|
-
|
|
17852
|
-
|
|
17853
|
-
} else {
|
|
17854
|
-
label = "Earlier";
|
|
17855
|
-
}
|
|
17856
|
-
if (!groups[label]) {
|
|
17857
|
-
groups[label] = [];
|
|
17858
|
-
order.push(label);
|
|
17859
|
-
}
|
|
17860
|
-
groups[label].push(n);
|
|
17087
|
+
const at = datedMillis(n.timestamp);
|
|
17088
|
+
const label = !Number.isFinite(at) || at < yesterdayStarts ? "Earlier" : at < todayStarts ? "Yesterday" : "Today";
|
|
17089
|
+
groups.get(label).push(n);
|
|
17861
17090
|
}
|
|
17862
|
-
return
|
|
17091
|
+
return DAY_GROUPS.filter((label) => groups.get(label).length > 0).map((label) => ({ label, items: groups.get(label) }));
|
|
17863
17092
|
}
|
|
17864
17093
|
function Tour({ steps, open, onClose, onComplete, container }) {
|
|
17865
17094
|
const [current, setCurrent] = useState(0);
|
|
@@ -18254,8 +17483,8 @@ function useFlowSteps(options) {
|
|
|
18254
17483
|
go(target, { replace: true });
|
|
18255
17484
|
}, [key, stored, valid, furthest, href, go, at]);
|
|
18256
17485
|
useEffect(() => {
|
|
18257
|
-
if (key && ready
|
|
18258
|
-
}, [key, ready,
|
|
17486
|
+
if (key && ready) update(key, (v) => v.current === step ? v : { ...v, current: step });
|
|
17487
|
+
}, [key, ready, step]);
|
|
18259
17488
|
useEffect(() => {
|
|
18260
17489
|
if (!key || !ready) return;
|
|
18261
17490
|
const store = storeFor(key);
|
|
@@ -18659,57 +17888,7 @@ function DangerZone({ title = "Danger zone", description, children, className })
|
|
|
18659
17888
|
)
|
|
18660
17889
|
] });
|
|
18661
17890
|
}
|
|
18662
|
-
var lineClampClasses = {
|
|
18663
|
-
1: "truncate",
|
|
18664
|
-
2: "line-clamp-2",
|
|
18665
|
-
3: "line-clamp-3",
|
|
18666
|
-
4: "line-clamp-4",
|
|
18667
|
-
5: "line-clamp-5",
|
|
18668
|
-
6: "line-clamp-6"
|
|
18669
|
-
};
|
|
18670
|
-
function getTruncationClass(lines) {
|
|
18671
|
-
return lineClampClasses[lines] || `line-clamp-[${lines}]`;
|
|
18672
|
-
}
|
|
18673
|
-
var TextOverflow = forwardRef(function TextOverflow2({
|
|
18674
|
-
lines = 1,
|
|
18675
|
-
tooltip = true,
|
|
18676
|
-
tooltipContent,
|
|
18677
|
-
expandMode = "tooltip",
|
|
18678
|
-
as = "div",
|
|
18679
|
-
children,
|
|
18680
|
-
className
|
|
18681
|
-
}, forwardedRef) {
|
|
18682
|
-
const { ref: overflowRef, isTruncated } = useTextOverflow({ lines });
|
|
18683
|
-
const truncClass = getTruncationClass(lines);
|
|
18684
|
-
const Tag3 = as;
|
|
18685
|
-
const content = /* @__PURE__ */ jsx(
|
|
18686
|
-
Tag3,
|
|
18687
|
-
{
|
|
18688
|
-
ref: (node) => {
|
|
18689
|
-
overflowRef(node);
|
|
18690
|
-
if (typeof forwardedRef === "function") forwardedRef(node);
|
|
18691
|
-
else if (forwardedRef) forwardedRef.current = node;
|
|
18692
|
-
},
|
|
18693
|
-
className: cn(truncClass, "min-w-0", className),
|
|
18694
|
-
children
|
|
18695
|
-
}
|
|
18696
|
-
);
|
|
18697
|
-
if (!tooltip || !isTruncated) {
|
|
18698
|
-
return content;
|
|
18699
|
-
}
|
|
18700
|
-
const resolvedTooltipContent = tooltipContent ?? children;
|
|
18701
|
-
if (expandMode === "hovercard") {
|
|
18702
|
-
return /* @__PURE__ */ jsx(
|
|
18703
|
-
HoverCard,
|
|
18704
|
-
{
|
|
18705
|
-
content: /* @__PURE__ */ jsx("div", { className: "max-w-[320px] text-sm text-[var(--ds-text-primary)]", children: resolvedTooltipContent }),
|
|
18706
|
-
children: content
|
|
18707
|
-
}
|
|
18708
|
-
);
|
|
18709
|
-
}
|
|
18710
|
-
return /* @__PURE__ */ jsx(AutoTooltip, { content: resolvedTooltipContent, children: content });
|
|
18711
|
-
});
|
|
18712
17891
|
|
|
18713
|
-
export { Accordion, ActionPanel, ActionPanelGroup, AddAnother, Alert, AsidePanel, AvatarGroup, BottomNav, BulkActionBar, Calendar, Card, CardContent, CardDescription, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, ChatMessageList, ChatPanel,
|
|
17892
|
+
export { Accordion, ActionPanel, ActionPanelGroup, AddAnother, Alert, AsidePanel, AvatarGroup, BottomNav, BulkActionBar, Calendar, Card, CardContent, CardDescription, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, ChatMessageList, ChatPanel, Collapsible, CollapsibleContent, CollapsibleTrigger, ColorPicker, Combobox, CommandPalette, ContextMenu, CornerPanel, DEFAULT_DATE_RANGE_PRESETS, DangerZone, DataList, DateRangePicker, DescriptionList, Dialog, Dock, EmptyState, EntityCell, FileUpload, FlowSaved, FormWrapper, Gantt, 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, 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 };
|
|
18714
17893
|
//# sourceMappingURL=index.js.map
|
|
18715
17894
|
//# sourceMappingURL=index.js.map
|