gridsmith-ui 0.30.1 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +73 -1
- package/dist/charts.d.ts +114 -1
- package/dist/charts.js +1113 -206
- package/dist/charts.js.map +1 -1
- package/dist/chat.js +24 -10
- package/dist/chat.js.map +1 -1
- package/dist/{chunk-ULCACQSA.js → chunk-2Q4HOGEI.js} +16 -51
- package/dist/chunk-2Q4HOGEI.js.map +1 -0
- package/dist/{chunk-T52LAFKG.js → chunk-3J67NISC.js} +13 -15
- package/dist/chunk-3J67NISC.js.map +1 -0
- package/dist/{chunk-L6HWACK7.js → chunk-53F7GVBQ.js} +6 -3
- package/dist/chunk-53F7GVBQ.js.map +1 -0
- package/dist/{chunk-SLRTSBCJ.js → chunk-BKYWKMUN.js} +73 -678
- package/dist/chunk-BKYWKMUN.js.map +1 -0
- package/dist/{chunk-KMKBOTFR.js → chunk-EKWXPSTI.js} +10 -12
- package/dist/chunk-EKWXPSTI.js.map +1 -0
- package/dist/{chunk-SJZWEBHL.js → chunk-GP2COVJC.js} +24 -11
- package/dist/chunk-GP2COVJC.js.map +1 -0
- package/dist/{chunk-OVHBQT3Z.js → chunk-GT6M74IZ.js} +6 -6
- package/dist/{chunk-OVHBQT3Z.js.map → chunk-GT6M74IZ.js.map} +1 -1
- package/dist/{chunk-IELIF4PJ.js → chunk-HUNEJIKV.js} +3 -3
- package/dist/{chunk-IELIF4PJ.js.map → chunk-HUNEJIKV.js.map} +1 -1
- package/dist/{chunk-NEUWZUK6.js → chunk-LE72KHIE.js} +3 -4
- package/dist/chunk-LE72KHIE.js.map +1 -0
- package/dist/{chunk-OX3NNMWG.js → chunk-OFACAHRV.js} +10 -6
- package/dist/chunk-OFACAHRV.js.map +1 -0
- package/dist/{chunk-R5QXMNW7.js → chunk-OWQ7M6R7.js} +177 -27
- package/dist/chunk-OWQ7M6R7.js.map +1 -0
- package/dist/{chunk-TYNDXMBV.js → chunk-QOMP4D6V.js} +3 -3
- package/dist/{chunk-TYNDXMBV.js.map → chunk-QOMP4D6V.js.map} +1 -1
- package/dist/chunk-U7WBI4AV.js +285 -0
- package/dist/chunk-U7WBI4AV.js.map +1 -0
- package/dist/chunk-V2ARGHJN.js +755 -0
- package/dist/chunk-V2ARGHJN.js.map +1 -0
- package/dist/chunk-V73LHNRL.js +51 -0
- package/dist/chunk-V73LHNRL.js.map +1 -0
- package/dist/{chunk-UDJOIVKQ.js → chunk-XSQD3UGY.js} +77 -7
- package/dist/chunk-XSQD3UGY.js.map +1 -0
- package/dist/{chunk-ISONVOA7.js → chunk-YFHTREH5.js} +6 -8
- package/dist/chunk-YFHTREH5.js.map +1 -0
- package/dist/data-grid.js +10 -13
- package/dist/data-grid.js.map +1 -1
- package/dist/editor-mentions.js +2 -4
- package/dist/editor-mentions.js.map +1 -1
- package/dist/editor.js +3 -7
- package/dist/editor.js.map +1 -1
- package/dist/icons.js +1 -1
- package/dist/index.d.ts +104 -16
- package/dist/index.js +1075 -654
- package/dist/index.js.map +1 -1
- package/dist/kanban.js +9 -13
- package/dist/kanban.js.map +1 -1
- package/dist/resizable.js +9 -13
- package/dist/resizable.js.map +1 -1
- package/dist/virtualized.js +10 -13
- package/dist/virtualized.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-6C2IUMY7.js +0 -46
- package/dist/chunk-6C2IUMY7.js.map +0 -1
- package/dist/chunk-7Q46JXSK.js +0 -51
- package/dist/chunk-7Q46JXSK.js.map +0 -1
- package/dist/chunk-HTXP5BMM.js +0 -38
- package/dist/chunk-HTXP5BMM.js.map +0 -1
- package/dist/chunk-ISONVOA7.js.map +0 -1
- package/dist/chunk-KMKBOTFR.js.map +0 -1
- package/dist/chunk-L6HWACK7.js.map +0 -1
- package/dist/chunk-NEUWZUK6.js.map +0 -1
- package/dist/chunk-NKUCS67T.js +0 -13
- package/dist/chunk-NKUCS67T.js.map +0 -1
- package/dist/chunk-OX3NNMWG.js.map +0 -1
- package/dist/chunk-R5QXMNW7.js.map +0 -1
- package/dist/chunk-SJZWEBHL.js.map +0 -1
- package/dist/chunk-SLRTSBCJ.js.map +0 -1
- package/dist/chunk-T52LAFKG.js.map +0 -1
- package/dist/chunk-UDJOIVKQ.js.map +0 -1
- package/dist/chunk-ULCACQSA.js.map +0 -1
- package/dist/chunk-WIUGPZOH.js +0 -88
- package/dist/chunk-WIUGPZOH.js.map +0 -1
- package/dist/chunk-YL5KD5RC.js +0 -49
- package/dist/chunk-YL5KD5RC.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,49 +1,46 @@
|
|
|
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 } from './chunk-
|
|
5
|
-
export { Skeleton } from './chunk-
|
|
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-EKWXPSTI.js';
|
|
3
|
+
export { AppShell, Breadcrumbs, Drawer, SkipLink, useAppShell, useUnsavedChanges } from './chunk-EKWXPSTI.js';
|
|
4
|
+
import { Skeleton, TITLE_TEXT, SegmentedControl } from './chunk-U7WBI4AV.js';
|
|
5
|
+
export { SegmentedControl, Skeleton } from './chunk-U7WBI4AV.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 { DropdownMenu } from './chunk-
|
|
12
|
-
export { DropdownMenu } from './chunk-
|
|
7
|
+
import { Avatar, foldForSearch, useActiveOptionInView, shownMentions, matchMentions, mentionOptionId, MentionList, initialsOf } from './chunk-LE72KHIE.js';
|
|
8
|
+
export { Avatar } from './chunk-LE72KHIE.js';
|
|
9
|
+
import { Link } from './chunk-OFACAHRV.js';
|
|
10
|
+
export { CodeBlock, Divider, Link } from './chunk-OFACAHRV.js';
|
|
11
|
+
import { DropdownMenu } from './chunk-YFHTREH5.js';
|
|
12
|
+
export { DropdownMenu } from './chunk-YFHTREH5.js';
|
|
13
13
|
import { useFillHeight, FillContext } from './chunk-DBHVJ7Z3.js';
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
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-
|
|
18
|
-
export { Checkbox, CheckboxGroup, CheckboxGroupItem, DatePicker, HoverCard, TextOverflow } from './chunk-
|
|
19
|
-
import { useWholeListCheck, pagerPart, Pagination,
|
|
20
|
-
export {
|
|
21
|
-
import { useShellPreferences, PREFERENCE_HOUSE_DEFAULTS, formatRelativeTime, thresholdOf, toMillis, formatFullTime, datedMillis, preferenceActionKey, DAY, HOUR, MINUTE } from './chunk-
|
|
22
|
-
export { PreferencesContext, formatFullTime, formatRelativeTime, preferenceActionKey, usePreferences } from './chunk-
|
|
14
|
+
import { Badge } from './chunk-GT6M74IZ.js';
|
|
15
|
+
export { Badge } from './chunk-GT6M74IZ.js';
|
|
16
|
+
import { useKeyboardScroll } from './chunk-GP2COVJC.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-3J67NISC.js';
|
|
18
|
+
export { Checkbox, CheckboxGroup, CheckboxGroupItem, DatePicker, HoverCard, TextOverflow } from './chunk-3J67NISC.js';
|
|
19
|
+
import { useWholeListCheck, pagerPart, Pagination, NumberInput } from './chunk-V2ARGHJN.js';
|
|
20
|
+
export { NumberInput, Pagination, Popover, usePagination } from './chunk-V2ARGHJN.js';
|
|
21
|
+
import { useShellPreferences, PREFERENCE_HOUSE_DEFAULTS, formatRelativeTime, thresholdOf, toMillis, formatFullTime, datedMillis, preferenceActionKey, DAY, HOUR, MINUTE } from './chunk-QOMP4D6V.js';
|
|
22
|
+
export { PreferencesContext, formatFullTime, formatRelativeTime, preferenceActionKey, usePreferences } from './chunk-QOMP4D6V.js';
|
|
23
23
|
import { useFormatLocale, useHydrated, useToday, LocaleContext } from './chunk-LJYSVZMI.js';
|
|
24
24
|
export { useFormatLocale, useHydrated } from './chunk-LJYSVZMI.js';
|
|
25
|
+
import { Input, CHECK_FILL, Dropdown, FilterRowContext, SWITCH_KNOB_ON, SWITCH_KNOB_OFF, SWITCH_KNOB_MOTION, SWITCH_TRACK_ON, SWITCH_TRACK_OFF, useFieldControl, useField, OutsideField, InlineFieldError, Label, AddAnotherRowCtx, Field } from './chunk-BKYWKMUN.js';
|
|
26
|
+
export { Dropdown, Field, InlineFieldError, Input, Label, Textarea, Toggle } from './chunk-BKYWKMUN.js';
|
|
25
27
|
import { formatLocale, localeChoice } from './chunk-7QLXYRPD.js';
|
|
26
28
|
import { useInputModality, inputModality } from './chunk-7RKC5C7G.js';
|
|
27
29
|
export { INPUT_MODALITY_ATTR, inputModality, installInputModality, useInputModality } from './chunk-7RKC5C7G.js';
|
|
28
30
|
import { FormChangeCtx, useReportedChange, useOptionalFormContext, FormCtx } from './chunk-72SDAX54.js';
|
|
29
31
|
export { useFormContext } from './chunk-72SDAX54.js';
|
|
30
|
-
import {
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
import { CardSurfaceCtx, useScrollsInside, SplitPaneCtx, RowsCtx, PageActionsCtx, SurfaceBoundary, useFramesItself, TableCardCtx } from './chunk-V73LHNRL.js';
|
|
33
|
+
import { Button, elementType, ControlSizeContext, triggerType, Spinner } from './chunk-2Q4HOGEI.js';
|
|
34
|
+
export { Button, ButtonSizeContext, ControlSizeContext, Spinner } from './chunk-2Q4HOGEI.js';
|
|
33
35
|
import { useBreakpoint, readBreakpointPx } from './chunk-ZHUVLBCC.js';
|
|
34
36
|
export { BreakpointWidthProvider, useBreakpoint } from './chunk-ZHUVLBCC.js';
|
|
35
|
-
import {
|
|
36
|
-
export {
|
|
37
|
-
import {
|
|
38
|
-
export {
|
|
39
|
-
import {
|
|
40
|
-
|
|
41
|
-
|
|
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';
|
|
37
|
+
import { useTextOverflow } from './chunk-HUNEJIKV.js';
|
|
38
|
+
export { useTextOverflow } from './chunk-HUNEJIKV.js';
|
|
39
|
+
import { AutoTooltip, mergeRefs, useRevealFocus } from './chunk-XSQD3UGY.js';
|
|
40
|
+
export { Tooltip, useRevealFocus } from './chunk-XSQD3UGY.js';
|
|
41
|
+
import { Icon, slotIcon, warnOnce } from './chunk-53F7GVBQ.js';
|
|
42
|
+
import { cn, FOCUS_RING, focusAfterSelfRemoval, FOCUSABLE, GLASS_SURFACE, useFocusKeptInList, FOCUS_INSET, useLatest, PEER_FOCUS_RING, GLASS_BACKDROP, FIELD, ZOOM_KEYS, rovingTabStop, FOCUS_ROOM, useOverlayLayer, useFocusTrap, useFocusBeforeOpen, rememberOpener, focusInitial, lockBodyScroll, unlockBodyScroll, OVERLAY_CLOSE_ATTR, OVERLAY_SURFACE, GLASS_OVERLAY, usePopupFocus, usePosition, ERROR_HAS_FOCUS_RING, FIELD_HAS_FOCUS_RING, CONTROL_ANCESTOR, GROUP_FOCUS_RING, useGridKeyboard, ERROR_ACTIVE_RING, ACTIVE_RING, ERROR_FOCUS_WITHIN_RING, FIELD_FOCUS_WITHIN_RING, focusAfterRemoval, GLASS_DROPDOWN, ERROR_FOCUS_RING, FIELD_FOCUS_RING, atLeastFocusRoom, useNonModalDialog, useReturnFocus } from './chunk-OWQ7M6R7.js';
|
|
43
|
+
export { useGridKeyboard } from './chunk-OWQ7M6R7.js';
|
|
47
44
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
48
45
|
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
46
|
import { createPortal, flushSync } from 'react-dom';
|
|
@@ -133,7 +130,7 @@ function Combobox({ value, onChange: onChangeProp, options, placeholder = "Searc
|
|
|
133
130
|
const onChange = useReportedChange(onChangeProp, value);
|
|
134
131
|
useInputModality();
|
|
135
132
|
const contextSize = useContext(ControlSizeContext);
|
|
136
|
-
const control = useFieldControl({ ...wiring, error: error || void 0 });
|
|
133
|
+
const control = useFieldControl({ ...wiring, "aria-label": ariaLabel, error: error || void 0 }, { component: "Combobox" });
|
|
137
134
|
const size = sizeProp ?? contextSize ?? "md";
|
|
138
135
|
const [open, setOpen] = useState(false);
|
|
139
136
|
useOverlayLayer(open);
|
|
@@ -262,8 +259,8 @@ function Combobox({ value, onChange: onChangeProp, options, placeholder = "Searc
|
|
|
262
259
|
type: "text",
|
|
263
260
|
id: control.id,
|
|
264
261
|
role: "combobox",
|
|
265
|
-
"aria-labelledby": wiring["aria-labelledby"],
|
|
266
|
-
"aria-label": control.labelId ? void 0 :
|
|
262
|
+
"aria-labelledby": control.shown ? void 0 : wiring["aria-labelledby"],
|
|
263
|
+
"aria-label": control.labelId ? void 0 : control.label,
|
|
267
264
|
"aria-describedby": control.describedBy,
|
|
268
265
|
"aria-invalid": control.invalid || void 0,
|
|
269
266
|
"aria-required": control.required || void 0,
|
|
@@ -424,6 +421,8 @@ function zoneOptions(locale) {
|
|
|
424
421
|
return zoneLists(key, build2).options;
|
|
425
422
|
}
|
|
426
423
|
function TimezoneSelect({ value, onChange, placeholder = "Search time zones\u2026", ...rest }) {
|
|
424
|
+
const control = useFieldControl(rest, { component: "TimezoneSelect" });
|
|
425
|
+
const { "aria-label": _pageLabel, "aria-labelledby": pageLabelledBy, ...comboboxRest } = rest;
|
|
427
426
|
const locale = useFormatLocale();
|
|
428
427
|
const zones = zoneOptions(locale);
|
|
429
428
|
const stored = value ? canonicalTimeZone(value) : "";
|
|
@@ -436,7 +435,7 @@ function TimezoneSelect({ value, onChange, placeholder = "Search time zones\u202
|
|
|
436
435
|
}
|
|
437
436
|
return zones.some((o) => o.value === stored) ? zones : [{ value: stored, label: labelOf(stored, /* @__PURE__ */ new Date(), locale), keywords: CITY_OF.get(stored) }, ...zones];
|
|
438
437
|
}, [zones, stored, mine, locale]);
|
|
439
|
-
return /* @__PURE__ */ jsx(Combobox, { value: stored, onChange, options, placeholder, ...
|
|
438
|
+
return /* @__PURE__ */ jsx(Combobox, { value: stored, onChange, options, placeholder, ...comboboxRest, "aria-label": control.shown ? void 0 : control.label, "aria-labelledby": control.shown ? void 0 : pageLabelledBy });
|
|
440
439
|
}
|
|
441
440
|
var LONGEST_WAIT = DAY;
|
|
442
441
|
var noChange = () => () => {
|
|
@@ -511,7 +510,7 @@ function RadioGroup({ value, onChange: onChangeProp, options, orientation = "ver
|
|
|
511
510
|
const onChange = useReportedChange(onChangeProp, value);
|
|
512
511
|
const groupRef = useRef(null);
|
|
513
512
|
const groupId = useId();
|
|
514
|
-
const control = useFieldControl(wiring);
|
|
513
|
+
const control = useFieldControl(wiring, { component: "RadioGroup", ownLabel: label ? groupId : void 0 });
|
|
515
514
|
const enabledOptions = options.filter((o) => !o.disabled);
|
|
516
515
|
const tabStop = rovingTabStop(options, (o) => o.value === value, (o) => !!o.disabled);
|
|
517
516
|
function handleKeyDown(e) {
|
|
@@ -543,8 +542,8 @@ function RadioGroup({ value, onChange: onChangeProp, options, orientation = "ver
|
|
|
543
542
|
ref: groupRef,
|
|
544
543
|
role: "radiogroup",
|
|
545
544
|
id: control.id,
|
|
546
|
-
"aria-label":
|
|
547
|
-
"aria-labelledby":
|
|
545
|
+
"aria-label": control.labelId ? void 0 : control.label,
|
|
546
|
+
"aria-labelledby": control.labelId,
|
|
548
547
|
"aria-describedby": control.describedBy,
|
|
549
548
|
"aria-invalid": control.invalid || void 0,
|
|
550
549
|
"aria-required": control.required || void 0,
|
|
@@ -671,7 +670,7 @@ function DateRangePicker({
|
|
|
671
670
|
const presetEdges = useScrollEdges({ enabled: isPhone });
|
|
672
671
|
useRevealFocus(presetEdges.elRef, isPhone);
|
|
673
672
|
const generatedId = useId();
|
|
674
|
-
const control = useFieldControl({ ...wiring, id, error: error || void 0 }, { requiredInDescription: true });
|
|
673
|
+
const control = useFieldControl({ ...wiring, id, error: error || void 0 }, { requiredInDescription: true, component: "DateRangePicker", ownLabel: label ? true : void 0 });
|
|
675
674
|
useInputModality();
|
|
676
675
|
const triggerId = control.id ?? generatedId;
|
|
677
676
|
const locale = useFormatLocale();
|
|
@@ -1563,6 +1562,8 @@ function RecurrencePicker({ value, onChange: onChangeProp, start, label, weekSta
|
|
|
1563
1562
|
setCustomOpen(false);
|
|
1564
1563
|
onChange(presets[Number(id.slice("preset-".length))].rule);
|
|
1565
1564
|
};
|
|
1565
|
+
const { "aria-label": pageName, "aria-labelledby": pageLabelledBy, ...choiceWiring } = wiring;
|
|
1566
|
+
const named = pageName || pageLabelledBy ? { role: "group", "aria-label": pageName, "aria-labelledby": pageLabelledBy } : {};
|
|
1566
1567
|
const summary = rule && !noDays(rule) ? describeRecurrence(rule, start, locale) : unreadable ? "Repeats by a rule set in another app. Choose another to replace it." : null;
|
|
1567
1568
|
const describedBy = [wiring["aria-describedby"], summary ? ids.summary : void 0].filter(Boolean).join(" ") || void 0;
|
|
1568
1569
|
const order = Array.from({ length: 7 }, (_, i) => (weekStart + i) % 7);
|
|
@@ -1574,17 +1575,17 @@ function RecurrencePicker({ value, onChange: onChangeProp, start, label, weekSta
|
|
|
1574
1575
|
const monthlyOn = custom?.nth ? nthId(custom.nth) : custom?.day === -1 ? "last" : "day";
|
|
1575
1576
|
const ends = custom?.until ? "until" : custom?.count !== void 0 ? "count" : untilPending ? "until" : "never";
|
|
1576
1577
|
if (!hydrated) {
|
|
1577
|
-
return /* @__PURE__ */ jsxs("div", { "data-gs": "recurrence-picker", "data-recurrence-pending": "", "aria-busy": "true", className: cn("space-y-ds-2", className), children: [
|
|
1578
|
-
/* @__PURE__ */ jsx(Dropdown, { ...
|
|
1578
|
+
return /* @__PURE__ */ jsxs("div", { "data-gs": "recurrence-picker", "data-recurrence-pending": "", "aria-busy": "true", ...named, className: cn("space-y-ds-2", className), children: [
|
|
1579
|
+
/* @__PURE__ */ jsx(Dropdown, { ...choiceWiring, label: field ? void 0 : label ?? "Repeat", options: PENDING_OPTIONS, value: "pending", onChange: () => {
|
|
1579
1580
|
} }),
|
|
1580
1581
|
(rule && !noDays(rule) || unreadable) && /* @__PURE__ */ jsx("p", { "aria-hidden": "true", className: "text-xs", children: "\xA0" })
|
|
1581
1582
|
] });
|
|
1582
1583
|
}
|
|
1583
|
-
return /* @__PURE__ */ jsxs("div", { "data-gs": "recurrence-picker", className: cn("space-y-ds-2", className), children: [
|
|
1584
|
+
return /* @__PURE__ */ jsxs("div", { "data-gs": "recurrence-picker", ...named, className: cn("space-y-ds-2", className), children: [
|
|
1584
1585
|
/* @__PURE__ */ jsx(
|
|
1585
1586
|
Dropdown,
|
|
1586
1587
|
{
|
|
1587
|
-
...
|
|
1588
|
+
...choiceWiring,
|
|
1588
1589
|
"aria-describedby": describedBy,
|
|
1589
1590
|
label: field ? void 0 : label ?? "Repeat",
|
|
1590
1591
|
options,
|
|
@@ -2087,7 +2088,7 @@ var running = (item) => item.status === "queued" || item.status === "uploading";
|
|
|
2087
2088
|
var failureOf = (err) => err instanceof Error && err.message ? err.message : "The upload didn't work.";
|
|
2088
2089
|
var percentOf = (value) => typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.min(100, value)) : 0;
|
|
2089
2090
|
var STILL_UPLOADING = "Wait for your files to finish uploading";
|
|
2090
|
-
function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accept, multiple = true, maxSize, className, error = false, label, id, "aria-label": ariaLabel }) {
|
|
2091
|
+
function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accept, multiple = true, maxSize, className, error = false, label, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy }) {
|
|
2091
2092
|
const controlled = files !== void 0;
|
|
2092
2093
|
const [own, setOwn] = useState([]);
|
|
2093
2094
|
const shown = controlled ? files : own;
|
|
@@ -2107,6 +2108,7 @@ function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accep
|
|
|
2107
2108
|
const constraintsId = `${ownId}-constraints`;
|
|
2108
2109
|
const rejectedId = `${ownId}-rejected`;
|
|
2109
2110
|
const showLabel = label != null && !field;
|
|
2111
|
+
const control = useFieldControl({ "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy }, { component: "FileUpload", ownLabel: showLabel ? true : void 0 });
|
|
2110
2112
|
const constraints = fileConstraints(accept, maxSize, multiple);
|
|
2111
2113
|
const patch = (itemId, change) => setOwn((prev) => prev.map((i) => i.id === itemId ? { ...i, ...change } : i));
|
|
2112
2114
|
const stop = (itemId) => {
|
|
@@ -2318,8 +2320,8 @@ function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accep
|
|
|
2318
2320
|
accept,
|
|
2319
2321
|
multiple,
|
|
2320
2322
|
className: "sr-only",
|
|
2321
|
-
"aria-label":
|
|
2322
|
-
"aria-labelledby":
|
|
2323
|
+
"aria-label": control.labelId ? void 0 : control.label,
|
|
2324
|
+
"aria-labelledby": control.labelId,
|
|
2323
2325
|
"aria-describedby": describedBy,
|
|
2324
2326
|
"aria-invalid": invalid || void 0,
|
|
2325
2327
|
onChange: (e) => {
|
|
@@ -2386,6 +2388,7 @@ function SliderRange({
|
|
|
2386
2388
|
error = false,
|
|
2387
2389
|
label,
|
|
2388
2390
|
"aria-label": ariaLabel,
|
|
2391
|
+
"aria-labelledby": ariaLabelledBy,
|
|
2389
2392
|
"aria-describedby": describedByProp,
|
|
2390
2393
|
trackStyle,
|
|
2391
2394
|
formatValue
|
|
@@ -2394,9 +2397,10 @@ function SliderRange({
|
|
|
2394
2397
|
const field = useField();
|
|
2395
2398
|
const ownId = useId();
|
|
2396
2399
|
const showLabel = label != null && !field;
|
|
2397
|
-
const
|
|
2400
|
+
const control = useFieldControl({ "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy }, { component: "SliderRange", ownLabel: showLabel ? `${ownId}-label` : void 0 });
|
|
2401
|
+
const nameId = control.labelId;
|
|
2398
2402
|
const describedBy = [...new Set([describedByProp, field?.describedBy].join(" ").split(" ").filter(Boolean))].join(" ") || void 0;
|
|
2399
|
-
const thumbName = (part) => nameId ? { "aria-labelledby": part ? `${nameId} ${ownId}-${part}` : nameId } : { "aria-label":
|
|
2403
|
+
const thumbName = (part) => nameId ? { "aria-labelledby": part ? `${nameId} ${ownId}-${part}` : nameId } : { "aria-label": control.label ? part ? `${control.label} ${part}` : control.label : void 0 };
|
|
2400
2404
|
const isRange = Array.isArray(value);
|
|
2401
2405
|
const low = isRange ? value[0] : value;
|
|
2402
2406
|
const high = isRange ? value[1] : value;
|
|
@@ -2610,7 +2614,7 @@ function TimePicker({
|
|
|
2610
2614
|
}) {
|
|
2611
2615
|
const onChange = useReportedChange(onChangeProp, value);
|
|
2612
2616
|
const contextSize = useContext(ControlSizeContext);
|
|
2613
|
-
const control = useFieldControl({ ...wiring, id, error: error || void 0 }, { requiredInDescription: true });
|
|
2617
|
+
const control = useFieldControl({ ...wiring, id, error: error || void 0 }, { requiredInDescription: true, component: "TimePicker" });
|
|
2614
2618
|
useInputModality();
|
|
2615
2619
|
const size = sizeProp ?? contextSize ?? "md";
|
|
2616
2620
|
const [open, setOpen] = useState(false);
|
|
@@ -3296,6 +3300,7 @@ function PinInput({
|
|
|
3296
3300
|
id,
|
|
3297
3301
|
"aria-label": ariaLabel
|
|
3298
3302
|
}) {
|
|
3303
|
+
const control = useFieldControl({ "aria-label": ariaLabel }, { component: "PinInput" });
|
|
3299
3304
|
const onChange = useReportedChange(onChangeProp, value);
|
|
3300
3305
|
useInputModality();
|
|
3301
3306
|
const contextSize = useContext(ControlSizeContext);
|
|
@@ -3353,7 +3358,8 @@ function PinInput({
|
|
|
3353
3358
|
"div",
|
|
3354
3359
|
{
|
|
3355
3360
|
role: "group",
|
|
3356
|
-
"aria-
|
|
3361
|
+
"aria-labelledby": control.labelId,
|
|
3362
|
+
"aria-label": control.labelId ? void 0 : control.label ?? "PIN input",
|
|
3357
3363
|
"aria-invalid": error || void 0,
|
|
3358
3364
|
className: cn("inline-flex w-fit items-center gap-ds-2", className),
|
|
3359
3365
|
children: digits.map((digit, i) => /* @__PURE__ */ jsx(
|
|
@@ -3445,7 +3451,8 @@ function Rating({
|
|
|
3445
3451
|
const onChange = useReportedChange(onChangeProp, value);
|
|
3446
3452
|
const [hoverValue, setHoverValue] = useState(null);
|
|
3447
3453
|
const displayValue = hoverValue ?? value;
|
|
3448
|
-
const control = useFieldControl({ ...wiring, error: error || void 0 });
|
|
3454
|
+
const control = useFieldControl({ ...wiring, error: error || void 0 }, { component: "Rating" });
|
|
3455
|
+
const valueId = `${useId()}-value`;
|
|
3449
3456
|
const handleClick = useCallback(
|
|
3450
3457
|
(starIdx, isLeftHalf) => {
|
|
3451
3458
|
if (readOnly || !onChangeProp) return;
|
|
@@ -3508,13 +3515,13 @@ function Rating({
|
|
|
3508
3515
|
i
|
|
3509
3516
|
);
|
|
3510
3517
|
});
|
|
3511
|
-
return /* @__PURE__ */
|
|
3518
|
+
return /* @__PURE__ */ jsxs(
|
|
3512
3519
|
"div",
|
|
3513
3520
|
{
|
|
3514
3521
|
role: readOnly ? "img" : "radiogroup",
|
|
3515
3522
|
id: control.id,
|
|
3516
|
-
"aria-label": readOnly ? `${control.label ?? "Rating"}: ${value} out of ${max}` : control.
|
|
3517
|
-
"aria-labelledby": readOnly ?
|
|
3523
|
+
"aria-label": control.labelId ? void 0 : readOnly ? `${control.label ?? "Rating"}: ${value} out of ${max}` : control.label ?? `Rating: ${value} out of ${max}`,
|
|
3524
|
+
"aria-labelledby": readOnly && control.labelId ? `${control.labelId} ${valueId}` : control.labelId,
|
|
3518
3525
|
"aria-describedby": control.describedBy,
|
|
3519
3526
|
"aria-invalid": readOnly ? void 0 : control.invalid || void 0,
|
|
3520
3527
|
"aria-required": readOnly ? void 0 : control.required || void 0,
|
|
@@ -3527,7 +3534,10 @@ function Rating({
|
|
|
3527
3534
|
className
|
|
3528
3535
|
),
|
|
3529
3536
|
onMouseLeave: () => setHoverValue(null),
|
|
3530
|
-
children:
|
|
3537
|
+
children: [
|
|
3538
|
+
readOnly && control.labelId && /* @__PURE__ */ jsx("span", { id: valueId, hidden: true, children: `${value} out of ${max}` }),
|
|
3539
|
+
stars
|
|
3540
|
+
]
|
|
3531
3541
|
}
|
|
3532
3542
|
);
|
|
3533
3543
|
}
|
|
@@ -3594,28 +3604,103 @@ var DEFAULT_SWATCHES = [
|
|
|
3594
3604
|
"#000000",
|
|
3595
3605
|
"#ffffff"
|
|
3596
3606
|
];
|
|
3607
|
+
function parseHex(value) {
|
|
3608
|
+
return /^#?([0-9a-f]{6}|[0-9a-f]{8})$/i.test(value.trim()) ? hexToHsl(value.trim()) : null;
|
|
3609
|
+
}
|
|
3610
|
+
var sameColor = (a, b) => a.trim().toLowerCase() === b.trim().toLowerCase();
|
|
3611
|
+
var NEUTRAL = { h: 0, s: 0, l: 50, a: 1 };
|
|
3597
3612
|
function ColorPicker({
|
|
3598
3613
|
value,
|
|
3599
3614
|
onChange: onChangeProp,
|
|
3600
3615
|
showAlpha = false,
|
|
3601
3616
|
swatches = DEFAULT_SWATCHES,
|
|
3617
|
+
swatchesOnly = false,
|
|
3602
3618
|
disabled = false,
|
|
3603
3619
|
className,
|
|
3604
|
-
|
|
3605
|
-
"aria-label": ariaLabel
|
|
3620
|
+
...wiring
|
|
3606
3621
|
}) {
|
|
3622
|
+
const control = useFieldControl(wiring, { requiredInDescription: !swatchesOnly, component: "ColorPicker" });
|
|
3623
|
+
const named = {
|
|
3624
|
+
id: control.id,
|
|
3625
|
+
"aria-label": control.labelId ? void 0 : control.label,
|
|
3626
|
+
"aria-labelledby": control.labelId,
|
|
3627
|
+
"aria-describedby": control.describedBy,
|
|
3628
|
+
"aria-invalid": control.invalid || void 0
|
|
3629
|
+
};
|
|
3607
3630
|
const onChange = useReportedChange(onChangeProp, value);
|
|
3608
3631
|
useInputModality();
|
|
3609
|
-
const [hsl, setHsl] = useState(() =>
|
|
3632
|
+
const [hsl, setHsl] = useState(() => parseHex(value) ?? NEUTRAL);
|
|
3610
3633
|
const [hexInput, setHexInput] = useState(value);
|
|
3611
3634
|
const satLightRef = useRef(null);
|
|
3612
3635
|
const draggingRef = useRef(false);
|
|
3636
|
+
const swatchRefs = useRef([]);
|
|
3613
3637
|
const [prevValue, setPrevValue] = useState(value);
|
|
3614
3638
|
if (value !== prevValue) {
|
|
3615
3639
|
setPrevValue(value);
|
|
3616
|
-
setHsl(
|
|
3640
|
+
setHsl((was) => parseHex(value) ?? was);
|
|
3617
3641
|
setHexInput(value);
|
|
3618
3642
|
}
|
|
3643
|
+
const items = swatches.map((s) => typeof s === "string" ? { value: s, label: s } : s);
|
|
3644
|
+
const repeated = items.find((s, i) => items.findIndex((o) => sameColor(o.value, s.value)) !== i)?.value;
|
|
3645
|
+
useEffect(() => {
|
|
3646
|
+
if (repeated) warnOnce("ColorPicker", `two swatches share the colour "${repeated}": give each swatch a colour of its own, so the one chosen is the one shown as chosen.`);
|
|
3647
|
+
}, [repeated]);
|
|
3648
|
+
const chosen = items.findIndex((s) => sameColor(s.value, value));
|
|
3649
|
+
const stop = Math.max(0, chosen);
|
|
3650
|
+
const choose = (index) => {
|
|
3651
|
+
const swatch = items[index];
|
|
3652
|
+
if (!swatch || disabled) return;
|
|
3653
|
+
setHsl((was) => parseHex(swatch.value) ?? was);
|
|
3654
|
+
setHexInput(swatch.value);
|
|
3655
|
+
if (!sameColor(swatch.value, value)) onChange(swatch.value);
|
|
3656
|
+
};
|
|
3657
|
+
const onSwatchKey = (e, index) => {
|
|
3658
|
+
const step = e.key === "ArrowRight" || e.key === "ArrowDown" ? 1 : e.key === "ArrowLeft" || e.key === "ArrowUp" ? -1 : 0;
|
|
3659
|
+
const to = step ? (index + step + items.length) % items.length : e.key === "Home" ? 0 : e.key === "End" ? items.length - 1 : -1;
|
|
3660
|
+
if (to < 0) return;
|
|
3661
|
+
e.preventDefault();
|
|
3662
|
+
swatchRefs.current[to]?.focus();
|
|
3663
|
+
choose(to);
|
|
3664
|
+
};
|
|
3665
|
+
const swatchRow = /* @__PURE__ */ jsx(
|
|
3666
|
+
"div",
|
|
3667
|
+
{
|
|
3668
|
+
role: "radiogroup",
|
|
3669
|
+
...swatchesOnly ? { ...named, "aria-required": control.required || void 0 } : { "aria-label": "Swatches" },
|
|
3670
|
+
"aria-disabled": disabled || void 0,
|
|
3671
|
+
className: cn("flex flex-wrap gap-ds-2", swatchesOnly && disabled && "opacity-disabled", swatchesOnly && className),
|
|
3672
|
+
children: items.map((swatch, i) => /* @__PURE__ */ jsx(AutoTooltip, { content: swatch.label, children: /* @__PURE__ */ jsx(
|
|
3673
|
+
"button",
|
|
3674
|
+
{
|
|
3675
|
+
ref: (el) => {
|
|
3676
|
+
swatchRefs.current[i] = el;
|
|
3677
|
+
},
|
|
3678
|
+
type: "button",
|
|
3679
|
+
role: "radio",
|
|
3680
|
+
"aria-checked": i === chosen,
|
|
3681
|
+
"aria-label": swatch.label,
|
|
3682
|
+
tabIndex: i === stop ? 0 : -1,
|
|
3683
|
+
disabled,
|
|
3684
|
+
onClick: () => choose(i),
|
|
3685
|
+
onKeyDown: (e) => onSwatchKey(e, i),
|
|
3686
|
+
className: cn(
|
|
3687
|
+
"w-7 h-7 rounded-[var(--ds-radius-sm)] cursor-pointer disabled:cursor-not-allowed",
|
|
3688
|
+
"flex items-center justify-center",
|
|
3689
|
+
"border-[length:var(--ds-border-width)]",
|
|
3690
|
+
"hover:scale-110 transition-transform",
|
|
3691
|
+
FOCUS_RING,
|
|
3692
|
+
// selected is a choice's look: the accent border, never the halo (that is active's) or an outline
|
|
3693
|
+
i === chosen ? "border-[var(--ds-accent-ink)]" : "border-[var(--ds-border-default)]"
|
|
3694
|
+
),
|
|
3695
|
+
style: { backgroundColor: swatch.value },
|
|
3696
|
+
children: i === chosen && /* @__PURE__ */ jsxs("svg", { "data-swatch-check": "", "aria-hidden": "true", width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", strokeLinecap: "round", strokeLinejoin: "round", className: "pointer-events-none", children: [
|
|
3697
|
+
/* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5", vectorEffect: "non-scaling-stroke", strokeWidth: 6.5, style: { stroke: "var(--ds-text-primary)" } }),
|
|
3698
|
+
/* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5", vectorEffect: "non-scaling-stroke", strokeWidth: 2.5, style: { stroke: "var(--ds-bg-canvas)" } })
|
|
3699
|
+
] })
|
|
3700
|
+
}
|
|
3701
|
+
) }, `${swatch.value}-${i}`))
|
|
3702
|
+
}
|
|
3703
|
+
);
|
|
3619
3704
|
const emitChange = useCallback(
|
|
3620
3705
|
(newHsl) => {
|
|
3621
3706
|
setHsl(newHsl);
|
|
@@ -3664,23 +3749,24 @@ function ColorPicker({
|
|
|
3664
3749
|
},
|
|
3665
3750
|
[onChange]
|
|
3666
3751
|
);
|
|
3752
|
+
if (swatchesOnly) return swatchRow;
|
|
3667
3753
|
return /* @__PURE__ */ jsxs(
|
|
3668
3754
|
"div",
|
|
3669
3755
|
{
|
|
3670
3756
|
role: "group",
|
|
3671
|
-
|
|
3672
|
-
"aria-invalid": error || void 0,
|
|
3757
|
+
...named,
|
|
3673
3758
|
className: cn(
|
|
3674
3759
|
"w-full max-w-64 p-ds-3 space-y-ds-3",
|
|
3675
3760
|
"bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)]",
|
|
3676
3761
|
"border-[length:var(--ds-border-width)]",
|
|
3677
|
-
|
|
3762
|
+
control.invalid ? "border-[var(--ds-status-error)]" : "border-[var(--ds-border-default)]",
|
|
3678
3763
|
"rounded-[var(--ds-radius-lg)]",
|
|
3679
3764
|
"shadow-[var(--ds-shadow-md)]",
|
|
3680
3765
|
disabled && "opacity-disabled pointer-events-none",
|
|
3681
3766
|
className
|
|
3682
3767
|
),
|
|
3683
3768
|
children: [
|
|
3769
|
+
control.requiredNote,
|
|
3684
3770
|
/* @__PURE__ */ jsx(
|
|
3685
3771
|
"div",
|
|
3686
3772
|
{
|
|
@@ -3713,6 +3799,7 @@ function ColorPicker({
|
|
|
3713
3799
|
{
|
|
3714
3800
|
type: "range",
|
|
3715
3801
|
"aria-label": "Hue",
|
|
3802
|
+
disabled,
|
|
3716
3803
|
min: 0,
|
|
3717
3804
|
max: 360,
|
|
3718
3805
|
value: hsl.h,
|
|
@@ -3728,6 +3815,7 @@ function ColorPicker({
|
|
|
3728
3815
|
{
|
|
3729
3816
|
type: "range",
|
|
3730
3817
|
"aria-label": "Opacity",
|
|
3818
|
+
disabled,
|
|
3731
3819
|
min: 0,
|
|
3732
3820
|
max: 100,
|
|
3733
3821
|
value: Math.round(hsl.a * 100),
|
|
@@ -3743,7 +3831,7 @@ function ColorPicker({
|
|
|
3743
3831
|
"div",
|
|
3744
3832
|
{
|
|
3745
3833
|
className: "w-8 h-8 rounded-[var(--ds-radius-sm)] border-[length:var(--ds-border-width)] border-[var(--ds-border-default)] shrink-0",
|
|
3746
|
-
style: { backgroundColor: hslToHex(hsl) }
|
|
3834
|
+
style: { backgroundColor: parseHex(value) ? hslToHex(hsl) : value }
|
|
3747
3835
|
}
|
|
3748
3836
|
),
|
|
3749
3837
|
/* @__PURE__ */ jsx(
|
|
@@ -3751,6 +3839,7 @@ function ColorPicker({
|
|
|
3751
3839
|
{
|
|
3752
3840
|
type: "text",
|
|
3753
3841
|
"aria-label": "Hex colour",
|
|
3842
|
+
disabled,
|
|
3754
3843
|
value: hexInput,
|
|
3755
3844
|
onChange: (e) => handleHexChange(e.target.value),
|
|
3756
3845
|
className: cn(
|
|
@@ -3764,27 +3853,7 @@ function ColorPicker({
|
|
|
3764
3853
|
}
|
|
3765
3854
|
)
|
|
3766
3855
|
] }),
|
|
3767
|
-
swatches.length > 0 &&
|
|
3768
|
-
"button",
|
|
3769
|
-
{
|
|
3770
|
-
type: "button",
|
|
3771
|
-
onClick: () => {
|
|
3772
|
-
const parsed = hexToHsl(swatch);
|
|
3773
|
-
emitChange(parsed);
|
|
3774
|
-
},
|
|
3775
|
-
className: cn(
|
|
3776
|
-
"w-7 h-7 rounded-[var(--ds-radius-sm)] cursor-pointer",
|
|
3777
|
-
"border-[length:var(--ds-border-width)]",
|
|
3778
|
-
"hover:scale-110 transition-transform",
|
|
3779
|
-
FOCUS_RING,
|
|
3780
|
-
// selected is a choice's look: the accent border, never the halo (that is active's) or an outline
|
|
3781
|
-
swatch.toLowerCase() === value.toLowerCase() ? "border-[var(--ds-accent-ink)]" : "border-[var(--ds-border-default)]"
|
|
3782
|
-
),
|
|
3783
|
-
style: { backgroundColor: swatch },
|
|
3784
|
-
"aria-label": swatch
|
|
3785
|
-
},
|
|
3786
|
-
swatch
|
|
3787
|
-
)) })
|
|
3856
|
+
swatches.length > 0 && swatchRow
|
|
3788
3857
|
]
|
|
3789
3858
|
}
|
|
3790
3859
|
);
|
|
@@ -4516,7 +4585,7 @@ function MentionInput({
|
|
|
4516
4585
|
"aria-label": ariaLabel,
|
|
4517
4586
|
...wiring
|
|
4518
4587
|
}) {
|
|
4519
|
-
const control = useFieldControl({ ...wiring, error: error || void 0 });
|
|
4588
|
+
const control = useFieldControl({ ...wiring, "aria-label": ariaLabel, error: error || void 0 }, { component: "MentionInput" });
|
|
4520
4589
|
useInputModality();
|
|
4521
4590
|
const [internalValue, setInternalValue] = useState("");
|
|
4522
4591
|
const value = controlledValue ?? internalValue;
|
|
@@ -4635,8 +4704,8 @@ function MentionInput({
|
|
|
4635
4704
|
{
|
|
4636
4705
|
ref: inputRef,
|
|
4637
4706
|
id: control.id,
|
|
4638
|
-
"aria-labelledby": wiring["aria-labelledby"],
|
|
4639
|
-
"aria-label": control.labelId ? void 0 :
|
|
4707
|
+
"aria-labelledby": control.shown ? void 0 : wiring["aria-labelledby"],
|
|
4708
|
+
"aria-label": control.labelId ? void 0 : control.label,
|
|
4640
4709
|
"aria-describedby": control.describedBy,
|
|
4641
4710
|
"aria-invalid": control.invalid || void 0,
|
|
4642
4711
|
"aria-required": control.required || void 0,
|
|
@@ -5785,6 +5854,131 @@ function rowMarks(row, index, field, id) {
|
|
|
5785
5854
|
return typeof v === "string" || typeof v === "number" ? { "data-row-key": String(id) } : { "data-row-index": String(index) };
|
|
5786
5855
|
}
|
|
5787
5856
|
var idPart = (id) => String(id).replace(/\s+/g, "_");
|
|
5857
|
+
var an = (word) => /^[aeiou]/i.test(word) ? "an" : "a";
|
|
5858
|
+
var MAX_TREE_DEPTH = 64;
|
|
5859
|
+
var MAX_TREE_ROWS = 1e5;
|
|
5860
|
+
var COPY_BUDGET = 1e3;
|
|
5861
|
+
var isPlainObject = (o) => {
|
|
5862
|
+
const proto = Object.getPrototypeOf(o);
|
|
5863
|
+
return proto === Object.prototype || proto === null;
|
|
5864
|
+
};
|
|
5865
|
+
function isCopy(above, row, field) {
|
|
5866
|
+
if (above === row) return true;
|
|
5867
|
+
if (!Object.is(above[field], row[field])) return false;
|
|
5868
|
+
let left = COPY_BUDGET;
|
|
5869
|
+
const alike = (a, b) => {
|
|
5870
|
+
if (Object.is(a, b)) return true;
|
|
5871
|
+
if (typeof a === "function" && typeof b === "function") return true;
|
|
5872
|
+
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null || --left < 0) return false;
|
|
5873
|
+
if (isValidElement(a) || isValidElement(b)) return isValidElement(a) && isValidElement(b) && a.type === b.type && a.key === b.key && alike(a.props, b.props);
|
|
5874
|
+
if (Array.isArray(a) || Array.isArray(b)) return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((v, i) => alike(v, b[i]));
|
|
5875
|
+
if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
|
|
5876
|
+
if (!isPlainObject(a) || !isPlainObject(b)) return false;
|
|
5877
|
+
const keys = Object.keys(a);
|
|
5878
|
+
return keys.length === Object.keys(b).length && keys.every((k) => Object.hasOwn(b, k) && alike(a[k], b[k]));
|
|
5879
|
+
};
|
|
5880
|
+
return alike(above, row);
|
|
5881
|
+
}
|
|
5882
|
+
function treeOf(data, ids, field, childrenOf) {
|
|
5883
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
5884
|
+
const all = [];
|
|
5885
|
+
const own = /* @__PURE__ */ new Set();
|
|
5886
|
+
let unnamed = false;
|
|
5887
|
+
let repeated = null;
|
|
5888
|
+
let looped = null;
|
|
5889
|
+
let tooDeep = false;
|
|
5890
|
+
let tooMany = false;
|
|
5891
|
+
const named = (row) => {
|
|
5892
|
+
const v = row[field];
|
|
5893
|
+
if (typeof v !== "string" && typeof v !== "number") return false;
|
|
5894
|
+
if (own.has(String(v))) repeated ??= String(v);
|
|
5895
|
+
own.add(String(v));
|
|
5896
|
+
return true;
|
|
5897
|
+
};
|
|
5898
|
+
const roots = data.map((row, i) => ({ row, originalIdx: i, id: ids[i] ?? i, level: 1, parent: null, children: [] }));
|
|
5899
|
+
for (const node of roots) {
|
|
5900
|
+
byKey.set(String(node.id), node);
|
|
5901
|
+
if (!named(node.row)) unnamed = true;
|
|
5902
|
+
}
|
|
5903
|
+
const grow = (node, path) => {
|
|
5904
|
+
all.push(node);
|
|
5905
|
+
if (all.length >= MAX_TREE_ROWS) {
|
|
5906
|
+
tooMany = true;
|
|
5907
|
+
return;
|
|
5908
|
+
}
|
|
5909
|
+
const rows = childrenOf(node.row, { level: node.level, parent: node.parent?.row ?? null });
|
|
5910
|
+
if (!rows?.length) return;
|
|
5911
|
+
if (node.level >= MAX_TREE_DEPTH) {
|
|
5912
|
+
tooDeep = true;
|
|
5913
|
+
return;
|
|
5914
|
+
}
|
|
5915
|
+
path.push(node.row);
|
|
5916
|
+
rows.forEach((row, i) => {
|
|
5917
|
+
const place = `${node.id}/${i}`;
|
|
5918
|
+
if (path.some((above) => isCopy(above, row, field))) {
|
|
5919
|
+
looped ??= typeof row[field] === "string" || typeof row[field] === "number" ? String(row[field]) : place;
|
|
5920
|
+
return;
|
|
5921
|
+
}
|
|
5922
|
+
const hasOwn = named(row);
|
|
5923
|
+
if (!hasOwn) unnamed = true;
|
|
5924
|
+
const v = row[field];
|
|
5925
|
+
const id = hasOwn && !byKey.has(String(v)) ? v : hasOwn ? `${v}~${place}` : place;
|
|
5926
|
+
const child = { row, originalIdx: -1, id, level: node.level + 1, parent: node, children: [] };
|
|
5927
|
+
byKey.set(String(id), child);
|
|
5928
|
+
node.children.push(child);
|
|
5929
|
+
grow(child, path);
|
|
5930
|
+
});
|
|
5931
|
+
path.pop();
|
|
5932
|
+
};
|
|
5933
|
+
for (const node of roots) grow(node, []);
|
|
5934
|
+
return { roots, byKey, all, unnamed, repeated, looped, tooDeep, tooMany };
|
|
5935
|
+
}
|
|
5936
|
+
function keysUnder(node, out = []) {
|
|
5937
|
+
out.push(String(node.id));
|
|
5938
|
+
for (const child of node.children) keysUnder(child, out);
|
|
5939
|
+
return out;
|
|
5940
|
+
}
|
|
5941
|
+
function settleSelection(roots, chosen) {
|
|
5942
|
+
const set = new Set(chosen);
|
|
5943
|
+
const partly = /* @__PURE__ */ new Set();
|
|
5944
|
+
const down = (node, on) => {
|
|
5945
|
+
const now = on || set.has(String(node.id));
|
|
5946
|
+
if (now) set.add(String(node.id));
|
|
5947
|
+
for (const child of node.children) down(child, now);
|
|
5948
|
+
};
|
|
5949
|
+
const up = (node) => {
|
|
5950
|
+
const key = String(node.id);
|
|
5951
|
+
if (!node.children.length) return set.has(key) ? "all" : "none";
|
|
5952
|
+
const states = node.children.map(up);
|
|
5953
|
+
const all = states.every((s) => s === "all");
|
|
5954
|
+
if (all) set.add(key);
|
|
5955
|
+
else set.delete(key);
|
|
5956
|
+
if (!all && states.some((s) => s !== "none")) partly.add(key);
|
|
5957
|
+
return all ? "all" : partly.has(key) ? "some" : "none";
|
|
5958
|
+
};
|
|
5959
|
+
for (const root of roots) down(root, false);
|
|
5960
|
+
for (const root of roots) up(root);
|
|
5961
|
+
return { set, partly };
|
|
5962
|
+
}
|
|
5963
|
+
var TREE_TOGGLE = cn(
|
|
5964
|
+
"relative shrink-0 w-4 h-4 flex items-center justify-center cursor-pointer rounded-[var(--ds-radius-sm)]",
|
|
5965
|
+
"text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)]",
|
|
5966
|
+
"before:absolute before:left-1/2 before:top-1/2 before:h-6 before:w-6 before:-translate-x-1/2 before:-translate-y-1/2 before:content-['']",
|
|
5967
|
+
FOCUS_RING
|
|
5968
|
+
);
|
|
5969
|
+
function rowsOfKey(body, ownKey, key) {
|
|
5970
|
+
return key === "" ? [] : Array.from(body.querySelectorAll(`:scope > tr[data-grid-key="${CSS.escape(ownKey + key)}"], :scope > tr[data-panel-of="${CSS.escape(key)}"]`));
|
|
5971
|
+
}
|
|
5972
|
+
var HEAD_KEY = "head:";
|
|
5973
|
+
var TreeHeldCtx = createContext(false);
|
|
5974
|
+
var CARD_TOGGLE = cn(
|
|
5975
|
+
// at least 24 px tall: the card around it is a target too, so its own box must meet the size (WCAG 2.5.8)
|
|
5976
|
+
"inline-flex min-h-[24px] items-center gap-ds-1 text-xs font-medium cursor-pointer",
|
|
5977
|
+
"transition-colors duration-[var(--ds-transition-speed)]",
|
|
5978
|
+
"text-[var(--ds-accent-ink)] hover:bg-[var(--ds-accent-muted)]",
|
|
5979
|
+
"rounded-[var(--ds-radius-sm)] px-ds-1.5 py-ds-0.5 -mx-ds-1.5",
|
|
5980
|
+
FOCUS_RING
|
|
5981
|
+
);
|
|
5788
5982
|
function TableHeading({ title, description, actions, titleId, descriptionId, inset }) {
|
|
5789
5983
|
const heading = /* @__PURE__ */ jsx("h3", { id: titleId, className: TITLE_CLASSES, children: title });
|
|
5790
5984
|
const actionsBlock = actions ? /* @__PURE__ */ jsx("div", { className: HEADER_LAYOUT.actions, children: actions }) : null;
|
|
@@ -5822,6 +6016,12 @@ function Table({
|
|
|
5822
6016
|
selectable,
|
|
5823
6017
|
selectedRows = [],
|
|
5824
6018
|
onSelectionChange,
|
|
6019
|
+
selectedKeys,
|
|
6020
|
+
onSelectedKeysChange,
|
|
6021
|
+
getChildRows,
|
|
6022
|
+
openParents: openParentsProp,
|
|
6023
|
+
defaultOpenParents,
|
|
6024
|
+
onOpenParentsChange,
|
|
5825
6025
|
expandable,
|
|
5826
6026
|
renderExpanded,
|
|
5827
6027
|
rowKey = "id",
|
|
@@ -5882,8 +6082,13 @@ function Table({
|
|
|
5882
6082
|
},
|
|
5883
6083
|
[sortKey, sortDir, onSortChange, pager]
|
|
5884
6084
|
);
|
|
6085
|
+
const { ids: rowIds, repeated } = useMemo(() => rowIdsOf(data, rowKey), [data, rowKey]);
|
|
6086
|
+
const tree = useMemo(() => getChildRows ? treeOf(data, rowIds, rowKey, getChildRows) : null, [data, rowIds, rowKey, getChildRows]);
|
|
6087
|
+
const nested = tree;
|
|
6088
|
+
const idOf = (_row, index) => rowIds[index] ?? index;
|
|
5885
6089
|
const columnKeys = useMemo(() => columns.map((c) => c.key), [columns]);
|
|
5886
|
-
const
|
|
6090
|
+
const allRows = useMemo(() => nested ? nested.all.map((n) => n.row) : data, [nested, data]);
|
|
6091
|
+
const inferredKinds = useMemo(() => inferColumnKinds(allRows, columnKeys), [allRows, columnKeys]);
|
|
5887
6092
|
const kindOf2 = useCallback(
|
|
5888
6093
|
(col) => col.kind ?? inferredKinds.get(col.key),
|
|
5889
6094
|
[inferredKinds]
|
|
@@ -5891,9 +6096,9 @@ function Table({
|
|
|
5891
6096
|
const sortColumn = sortKey ? columns.find((c) => c.key === sortKey) : void 0;
|
|
5892
6097
|
const sortKind = sortColumn ? kindOf2(sortColumn) : void 0;
|
|
5893
6098
|
const locale = useFormatLocale();
|
|
5894
|
-
const { sortedAll, unsortable } = useMemo(() => {
|
|
6099
|
+
const { sortedAll, unsortable, childOrder } = useMemo(() => {
|
|
5895
6100
|
const indexed = data.map((row, i) => ({ row, originalIdx: i }));
|
|
5896
|
-
if (!sortKey || !sortDir) return { sortedAll: indexed, unsortable: null };
|
|
6101
|
+
if (!sortKey || !sortDir) return { sortedAll: indexed, unsortable: null, childOrder: null };
|
|
5897
6102
|
const read = (row) => {
|
|
5898
6103
|
if (sortColumn?.sortValue) return sortableValue(sortColumn.sortValue(row));
|
|
5899
6104
|
const v = sortableValue(row[sortKey]);
|
|
@@ -5901,29 +6106,33 @@ function Table({
|
|
|
5901
6106
|
return (sortKind === "number" ? numberOf(v) : sortKind === "date" ? timeOf(v) : void 0) ?? v;
|
|
5902
6107
|
};
|
|
5903
6108
|
const valued = indexed.map((entry) => ({ ...entry, value: read(entry.row) }));
|
|
5904
|
-
const
|
|
5905
|
-
const
|
|
6109
|
+
const levels = nested ? nested.all.filter((n) => n.children.length).map((n) => ({ key: String(n.id), rows: n.children.map((c) => ({ c, value: read(c.row) })) })) : [];
|
|
6110
|
+
const elements = valued.some((v) => v.value === null) || levels.some((l) => l.rows.some((r) => r.value === null));
|
|
6111
|
+
const compare = (a, b) => {
|
|
5906
6112
|
if (a.value === void 0 || b.value === void 0) return a.value === b.value ? 0 : a.value === void 0 ? 1 : -1;
|
|
5907
6113
|
const cmp = compareValues(a.value, b.value, locale);
|
|
5908
6114
|
return sortDir === "asc" ? cmp : -cmp;
|
|
5909
|
-
}
|
|
5910
|
-
|
|
5911
|
-
|
|
6115
|
+
};
|
|
6116
|
+
const sorted = elements ? indexed : valued.sort(compare);
|
|
6117
|
+
const childOrder2 = elements || !nested ? null : new Map(levels.map((l) => [l.key, l.rows.sort(compare).map((r) => r.c)]));
|
|
6118
|
+
return { sortedAll: sorted, unsortable: elements ? sortKey : null, childOrder: childOrder2 };
|
|
6119
|
+
}, [data, sortKey, sortDir, sortColumn, sortKind, locale, nested]);
|
|
5912
6120
|
const canSort = useMemo(() => {
|
|
5913
6121
|
const can = /* @__PURE__ */ new Set();
|
|
5914
|
-
for (const col of columns) if (col.sortValue ||
|
|
6122
|
+
for (const col of columns) if (col.sortValue || allRows.every((row) => sortableValue(row[col.key]) !== null)) can.add(col.key);
|
|
5915
6123
|
return can;
|
|
5916
|
-
}, [columns,
|
|
6124
|
+
}, [columns, allRows]);
|
|
5917
6125
|
useEffect(() => {
|
|
5918
6126
|
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).`);
|
|
5919
6127
|
}, [unsortable]);
|
|
5920
6128
|
const pageSorts = !!onSortChange;
|
|
6129
|
+
const sortsBy = (col) => col.header.trim() !== "" && (pageSorts ? col.sortable ?? (!!sortable && canSort.has(col.key)) : (col.sortable ?? !!sortable) && canSort.has(col.key));
|
|
5921
6130
|
const refused = pageSorts ? "" : columns.filter((col) => col.sortable && !canSort.has(col.key)).map((col) => col.key).join(", ");
|
|
5922
6131
|
useEffect(() => {
|
|
5923
6132
|
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
6133
|
}, [refused]);
|
|
5925
6134
|
useEffect(() => {
|
|
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
|
|
6135
|
+
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.`);
|
|
5927
6136
|
}, [pager, data.length]);
|
|
5928
6137
|
const rangeStart = pager ? pager.range[0] : null;
|
|
5929
6138
|
const rangeEnd2 = pager ? pager.range[1] : null;
|
|
@@ -5932,14 +6141,65 @@ function Table({
|
|
|
5932
6141
|
[sortedAll, rangeStart, rangeEnd2]
|
|
5933
6142
|
);
|
|
5934
6143
|
const drawnStart = rangeStart ? rangeStart - 1 : 0;
|
|
6144
|
+
const openControlled = openParentsProp !== void 0;
|
|
6145
|
+
const [ownOpen, setOwnOpen] = useState(defaultOpenParents ?? []);
|
|
6146
|
+
const open = openControlled ? openParentsProp : ownOpen;
|
|
6147
|
+
const openSet = new Set(open.map(String));
|
|
6148
|
+
const setOpen = (next) => {
|
|
6149
|
+
if (!openControlled) setOwnOpen(next);
|
|
6150
|
+
onOpenParentsChange?.(next);
|
|
6151
|
+
};
|
|
6152
|
+
const toggleOpen = (id) => setOpen(openSet.has(String(id)) ? open.filter((k) => String(k) !== String(id)) : [...open, id]);
|
|
6153
|
+
const visible = nested ? [] : null;
|
|
6154
|
+
if (nested && visible) {
|
|
6155
|
+
const walk = (nodes, first, size) => nodes.forEach((node, i) => {
|
|
6156
|
+
visible.push({ node, pos: first + i, size });
|
|
6157
|
+
if (!node.children.length || !openSet.has(String(node.id))) return;
|
|
6158
|
+
const under = childOrder?.get(String(node.id)) ?? node.children;
|
|
6159
|
+
walk(under, 1, under.length);
|
|
6160
|
+
});
|
|
6161
|
+
walk(drawn.map((d) => nested.roots[d.originalIdx]), drawnStart + 1, data.length);
|
|
6162
|
+
}
|
|
6163
|
+
const visibleKeys = visible ? visible.map((v) => String(v.node.id)) : [];
|
|
6164
|
+
const reportRows = useReportedChange(onSelectionChange, selectedRows);
|
|
6165
|
+
const reportKeys = useReportedChange(onSelectedKeysChange, selectedKeys);
|
|
5935
6166
|
const selectedSet = new Set(selectedRows);
|
|
5936
6167
|
const drawnIdx = drawn.map((d) => d.originalIdx);
|
|
5937
|
-
const
|
|
5938
|
-
const
|
|
6168
|
+
const keyed = selectedKeys !== void 0 || onSelectedKeysChange !== void 0;
|
|
6169
|
+
const chosen = useMemo(() => {
|
|
6170
|
+
if (!keyed) return null;
|
|
6171
|
+
const keys = (selectedKeys ?? []).map(String);
|
|
6172
|
+
return nested ? settleSelection(nested.roots, keys) : { set: new Set(keys), partly: /* @__PURE__ */ new Set() };
|
|
6173
|
+
}, [keyed, selectedKeys, nested]);
|
|
6174
|
+
const scopeKeys = chosen ? nested ? drawn.flatMap((d) => keysUnder(nested.roots[d.originalIdx])) : drawn.map((d) => String(idOf(d.row, d.originalIdx))) : null;
|
|
6175
|
+
const allSelected = scopeKeys ? scopeKeys.length > 0 && scopeKeys.every((k) => chosen.set.has(k)) : drawnIdx.length > 0 && drawnIdx.every((i) => selectedSet.has(i));
|
|
6176
|
+
const someSelected = !allSelected && (scopeKeys ? scopeKeys.some((k) => chosen.set.has(k)) : drawnIdx.some((i) => selectedSet.has(i)));
|
|
6177
|
+
const emitKeys = (next) => {
|
|
6178
|
+
const settled = nested ? settleSelection(nested.roots, next).set : next;
|
|
6179
|
+
const out = [];
|
|
6180
|
+
const placed = /* @__PURE__ */ new Set();
|
|
6181
|
+
const put = (key) => {
|
|
6182
|
+
if (!settled.has(String(key)) || placed.has(String(key))) return;
|
|
6183
|
+
placed.add(String(key));
|
|
6184
|
+
out.push(key);
|
|
6185
|
+
};
|
|
6186
|
+
for (const key of selectedKeys ?? []) put(key);
|
|
6187
|
+
for (const key of nested ? nested.all.map((n) => n.id) : rowIds) put(key);
|
|
6188
|
+
reportKeys(out);
|
|
6189
|
+
};
|
|
5939
6190
|
const toggleAll = () => {
|
|
6191
|
+
if (chosen && scopeKeys) {
|
|
6192
|
+
const next = new Set(chosen.set);
|
|
6193
|
+
for (const key of scopeKeys) {
|
|
6194
|
+
if (allSelected) next.delete(key);
|
|
6195
|
+
else next.add(key);
|
|
6196
|
+
}
|
|
6197
|
+
emitKeys(next);
|
|
6198
|
+
return;
|
|
6199
|
+
}
|
|
5940
6200
|
const shown = new Set(drawnIdx);
|
|
5941
|
-
if (allSelected)
|
|
5942
|
-
else
|
|
6201
|
+
if (allSelected) reportRows(selectedRows.filter((r) => !shown.has(r)));
|
|
6202
|
+
else reportRows([...selectedRows.filter((r) => !shown.has(r)), ...drawnIdx]);
|
|
5943
6203
|
};
|
|
5944
6204
|
const anchor = useRef(null);
|
|
5945
6205
|
const toggleRow = (idx, shiftKey2 = false) => {
|
|
@@ -5948,22 +6208,81 @@ function Table({
|
|
|
5948
6208
|
anchor.current = idx;
|
|
5949
6209
|
if (shiftKey2 && from >= 0 && to >= 0 && from !== to) {
|
|
5950
6210
|
const run = drawnIdx.slice(Math.min(from, to), Math.max(from, to) + 1);
|
|
5951
|
-
|
|
6211
|
+
reportRows([...selectedRows.filter((r) => !run.includes(r)), ...run]);
|
|
5952
6212
|
return;
|
|
5953
6213
|
}
|
|
5954
|
-
if (selectedSet.has(idx))
|
|
5955
|
-
else
|
|
6214
|
+
if (selectedSet.has(idx)) reportRows(selectedRows.filter((r) => r !== idx));
|
|
6215
|
+
else reportRows([...selectedRows, idx]);
|
|
6216
|
+
};
|
|
6217
|
+
const anchorKey = useRef(null);
|
|
6218
|
+
const toggleKey = (id, shiftKey2 = false) => {
|
|
6219
|
+
if (!chosen) return;
|
|
6220
|
+
const key = String(id);
|
|
6221
|
+
const node = nested?.byKey.get(key);
|
|
6222
|
+
const order = nested ? visibleKeys : drawn.map((d) => String(idOf(d.row, d.originalIdx)));
|
|
6223
|
+
const from = anchorKey.current === null ? -1 : order.indexOf(anchorKey.current);
|
|
6224
|
+
const to = order.indexOf(key);
|
|
6225
|
+
anchorKey.current = key;
|
|
6226
|
+
const under = (k) => {
|
|
6227
|
+
const n = nested?.byKey.get(k);
|
|
6228
|
+
return n ? keysUnder(n) : [k];
|
|
6229
|
+
};
|
|
6230
|
+
const next = new Set(chosen.set);
|
|
6231
|
+
if (shiftKey2 && from >= 0 && to >= 0 && from !== to) {
|
|
6232
|
+
for (const k of order.slice(Math.min(from, to), Math.max(from, to) + 1)) for (const s of under(k)) next.add(s);
|
|
6233
|
+
} else if (chosen.set.has(key)) {
|
|
6234
|
+
for (const s of under(key)) next.delete(s);
|
|
6235
|
+
for (let p = node?.parent; p; p = p.parent) next.delete(String(p.id));
|
|
6236
|
+
} else {
|
|
6237
|
+
for (const s of under(key)) next.add(s);
|
|
6238
|
+
}
|
|
6239
|
+
emitKeys(next);
|
|
6240
|
+
};
|
|
6241
|
+
const boxOf = (originalIdx, id) => {
|
|
6242
|
+
if (chosen) return { checked: chosen.set.has(String(id)), mixed: chosen.partly.has(String(id)) };
|
|
6243
|
+
return originalIdx < 0 ? null : { checked: selectedSet.has(originalIdx), mixed: false };
|
|
5956
6244
|
};
|
|
6245
|
+
const toggleBox = (originalIdx, id, shiftKey2 = false) => chosen ? toggleKey(id, shiftKey2) : toggleRow(originalIdx, shiftKey2);
|
|
6246
|
+
useEffect(() => {
|
|
6247
|
+
if (nested && selectable && !keyed) warnOnce("Table", "a tree table (getChildRows) selects by key: give it selectedKeys and onSelectedKeysChange, as a row under another has no index in data, and selectedRows reaches the top-level rows only.");
|
|
6248
|
+
}, [nested, selectable, keyed]);
|
|
6249
|
+
useEffect(() => {
|
|
6250
|
+
if (nested?.unnamed) warnOnce("Table", `a tree table (getChildRows) names its rows by their ${rowKey}: give every row its own, the rows under a row too (rowKey), so an open row, a selection and focus stay on their row.`);
|
|
6251
|
+
}, [nested, rowKey]);
|
|
6252
|
+
useEffect(() => {
|
|
6253
|
+
if (nested?.looped != null) warnOnce("Table", `a tree table's row "${nested.looped}" is under itself: getChildRows gave it, or a copy of it, among the rows under it or under a row below it, so the tree would never end, and it is left out there. Give getChildRows the rows each row holds, by the level and the parent it gives.`);
|
|
6254
|
+
}, [nested, rowKey]);
|
|
6255
|
+
useEffect(() => {
|
|
6256
|
+
if (nested?.tooMany) warnOnce("Table", `a tree table's rows come to more than ${MAX_TREE_ROWS.toLocaleString("en-GB")}, and the rest are drawn with no rows under them: give getChildRows an end, answering by the level it gives and giving no rows past the last level.`);
|
|
6257
|
+
}, [nested]);
|
|
6258
|
+
useEffect(() => {
|
|
6259
|
+
if (nested?.tooDeep) warnOnce("Table", `a tree table's rows go deeper than ${MAX_TREE_DEPTH} levels, and the last is drawn with no rows under it: give getChildRows's rows an end, answering by the level it gives.`);
|
|
6260
|
+
}, [nested]);
|
|
6261
|
+
useEffect(() => {
|
|
6262
|
+
if (nested?.repeated != null) warnOnce("Table", `a tree table (getChildRows) needs ${an(rowKey)} ${rowKey} of its own for each row, one per row across every level: "${nested.repeated}" names more than one, so an open row, a selection and focus may go to the other. Number the levels' rows apart ("task-3", "task-3/step-1").`);
|
|
6263
|
+
}, [nested, rowKey]);
|
|
5957
6264
|
const expandControlled = expandedRowsProp !== void 0;
|
|
5958
6265
|
const [ownExpanded, setOwnExpanded] = useState(defaultExpandedRows ?? []);
|
|
5959
6266
|
const expanded = expandControlled ? expandedRowsProp : ownExpanded;
|
|
5960
6267
|
const expandedSet = new Set(expanded.map(String));
|
|
5961
|
-
const
|
|
6268
|
+
const expandedKey = expanded.map(String).join("");
|
|
6269
|
+
const [revealed, setRevealed] = useState([]);
|
|
6270
|
+
if (nested && expandControlled) {
|
|
6271
|
+
const fresh = [...expandedSet].filter((key) => !revealed.includes(key) && nested.byKey.has(key));
|
|
6272
|
+
const kept = revealed.filter((key) => expandedSet.has(key));
|
|
6273
|
+
if (fresh.length || kept.length !== revealed.length) {
|
|
6274
|
+
setRevealed([...kept, ...fresh]);
|
|
6275
|
+
const shut = [];
|
|
6276
|
+
for (const key of fresh) {
|
|
6277
|
+
for (let p = nested.byKey.get(key)?.parent; p; p = p.parent) if (!openSet.has(String(p.id)) && !shut.includes(p.id)) shut.push(p.id);
|
|
6278
|
+
}
|
|
6279
|
+
if (shut.length && !openControlled) setOwnOpen([...ownOpen, ...shut]);
|
|
6280
|
+
}
|
|
6281
|
+
}
|
|
5962
6282
|
useEffect(() => {
|
|
5963
|
-
if (repeated !== null) warnOnce("Table", `two rows share the ${rowKey} "${repeated}": give each row its own, or name a field that is one (rowKey), so an opened row and focus stay on their row.`);
|
|
5964
|
-
}, [repeated, rowKey]);
|
|
5965
|
-
const
|
|
5966
|
-
const marksOf = (row, index) => rowMarks(row, index, rowKey, idOf(row, index));
|
|
6283
|
+
if (repeated !== null && !nested) warnOnce("Table", `two rows share the ${rowKey} "${repeated}": give each row its own, or name a field that is one (rowKey), so an opened row and focus stay on their row.`);
|
|
6284
|
+
}, [repeated, rowKey, nested]);
|
|
6285
|
+
const marksOf = (row, index, id = idOf(row, index)) => rowMarks(row, index < 0 ? String(id) : index, rowKey, id);
|
|
5967
6286
|
const openedHere = useRef(null);
|
|
5968
6287
|
const toggleExpand = (id) => {
|
|
5969
6288
|
const opening = !expandedSet.has(String(id));
|
|
@@ -5988,9 +6307,11 @@ function Table({
|
|
|
5988
6307
|
}, [ref, rootRef]);
|
|
5989
6308
|
const tableRef = useRef(null);
|
|
5990
6309
|
const [pins, setPins] = useState(NO_PINS);
|
|
5991
|
-
const
|
|
5992
|
-
const
|
|
5993
|
-
const
|
|
6310
|
+
const trail = expandable && nested ? 1 : 0;
|
|
6311
|
+
const lead = (selectable ? 1 : 0) + (expandable && !nested ? 1 : 0);
|
|
6312
|
+
const endColumns = columns.filter((c) => c.pin === "end").length;
|
|
6313
|
+
const endCount = endColumns + trail;
|
|
6314
|
+
const nameIndex = columns.length > endColumns ? lead : -1;
|
|
5994
6315
|
const { ref: scrollRef, elRef: scrollEl, measure: measureScroll, scrollable, edges, fadeProps } = useScrollEdges({
|
|
5995
6316
|
enabled: !isMobile,
|
|
5996
6317
|
noFade: { left: lead + (pins.nameFits ? 1 : 0) > 0, right: endCount > 0 }
|
|
@@ -6022,7 +6343,9 @@ function Table({
|
|
|
6022
6343
|
const nameFits = nameIndex >= 0 && frame > 0 && at + nameWidth + fromRight <= frame / 2;
|
|
6023
6344
|
if (nameFits) start.push(at);
|
|
6024
6345
|
const pad4 = (cell, side) => cell ? parseFloat(getComputedStyle(cell)[side]) || 0 : 0;
|
|
6025
|
-
|
|
6346
|
+
let trailing = 0;
|
|
6347
|
+
for (let i = cells.length - trail; i < cells.length; i++) trailing += widths[i] ?? 0;
|
|
6348
|
+
const panel = cells.length > lead ? [at + pad4(cells[lead], "paddingLeft"), trailing + pad4(cells[cells.length - 1 - trail], "paddingRight")] : null;
|
|
6026
6349
|
const next = { start, end, nameFits, frame, panel };
|
|
6027
6350
|
setPins((prev) => samePins(prev, next) ? prev : next);
|
|
6028
6351
|
};
|
|
@@ -6032,7 +6355,7 @@ function Table({
|
|
|
6032
6355
|
observer.observe(table2);
|
|
6033
6356
|
observer.observe(scroller);
|
|
6034
6357
|
return () => observer.disconnect();
|
|
6035
|
-
}, [isMobile, lead, endCount, nameIndex, scrollEl, columns, drawn.length]);
|
|
6358
|
+
}, [isMobile, lead, trail, endCount, nameIndex, scrollEl, columns, drawn.length, visibleKeys.length]);
|
|
6036
6359
|
const pinnedStart = lead + (pins.nameFits ? 1 : 0);
|
|
6037
6360
|
const pinStyle = (position, total) => {
|
|
6038
6361
|
if (position < pinnedStart && pins.start[position] !== void 0) {
|
|
@@ -6047,7 +6370,7 @@ function Table({
|
|
|
6047
6370
|
return void 0;
|
|
6048
6371
|
};
|
|
6049
6372
|
const pinFocus = (position, total) => {
|
|
6050
|
-
if (!onRowClick || !pinStyle(position, total)) return void 0;
|
|
6373
|
+
if (!(onRowClick || nested) || !pinStyle(position, total)) return void 0;
|
|
6051
6374
|
const fromEnd = total - 1 - position;
|
|
6052
6375
|
return cn(PIN_FOCUS, position === 0 && PIN_FOCUS_START, fromEnd === 0 && PIN_FOCUS_END);
|
|
6053
6376
|
};
|
|
@@ -6064,8 +6387,228 @@ function Table({
|
|
|
6064
6387
|
if (kind) next.set(col.key, kind);
|
|
6065
6388
|
}
|
|
6066
6389
|
setRenderedKinds((prev) => prev.size === next.size && [...next].every(([k, v]) => prev.get(k) === v) ? prev : next);
|
|
6067
|
-
}, [columns, kindOf2, drawn, isMobile]);
|
|
6068
|
-
const
|
|
6390
|
+
}, [columns, kindOf2, drawn, isMobile, visibleKeys.length]);
|
|
6391
|
+
const [focusKey, setFocusKey] = useState(null);
|
|
6392
|
+
const visibleSet = new Set(visibleKeys);
|
|
6393
|
+
const ownKey = `${headingId}~`;
|
|
6394
|
+
const gridKey = (key) => ownKey + key;
|
|
6395
|
+
const fromGrid = (attr) => attr !== null && attr.startsWith(ownKey) ? attr.slice(ownKey.length) : null;
|
|
6396
|
+
const heldOuter = useContext(TreeHeldCtx);
|
|
6397
|
+
const headKeys = nested ? [...selectable ? [`${HEAD_KEY}select`] : [], ...columns.filter(sortsBy).map((col) => `${HEAD_KEY}${col.key}`)] : [];
|
|
6398
|
+
const visibleJoined = visibleKeys.join("");
|
|
6399
|
+
const [stood, setStood] = useState({ joined: "", keys: [] });
|
|
6400
|
+
if (nested && focusKey !== null && !focusKey.startsWith(HEAD_KEY) && !nested.byKey.has(focusKey)) {
|
|
6401
|
+
const at = stood.keys.indexOf(focusKey);
|
|
6402
|
+
let next = null;
|
|
6403
|
+
for (let i = at - 1; at >= 0 && i >= 0 && next === null; i--) if (visibleSet.has(stood.keys[i])) next = stood.keys[i];
|
|
6404
|
+
for (let i = at + 1; at >= 0 && i < stood.keys.length && next === null; i++) if (visibleSet.has(stood.keys[i])) next = stood.keys[i];
|
|
6405
|
+
setFocusKey(next);
|
|
6406
|
+
}
|
|
6407
|
+
if (nested && stood.joined !== visibleJoined) setStood({ joined: visibleJoined, keys: visibleKeys });
|
|
6408
|
+
let activeKey = visibleKeys[0] ?? "";
|
|
6409
|
+
if (focusKey !== null && headKeys.includes(focusKey)) activeKey = focusKey;
|
|
6410
|
+
else {
|
|
6411
|
+
for (let n = focusKey === null ? void 0 : nested?.byKey.get(focusKey); n; n = n.parent ?? void 0) {
|
|
6412
|
+
if (visibleSet.has(String(n.id))) {
|
|
6413
|
+
activeKey = String(n.id);
|
|
6414
|
+
break;
|
|
6415
|
+
}
|
|
6416
|
+
}
|
|
6417
|
+
}
|
|
6418
|
+
const grid = useGridKeyboard({
|
|
6419
|
+
container: tableRef,
|
|
6420
|
+
active: activeKey,
|
|
6421
|
+
setActive: setFocusKey,
|
|
6422
|
+
keyOf: gridKey,
|
|
6423
|
+
move: (from, e) => {
|
|
6424
|
+
const node = nested?.byKey.get(from);
|
|
6425
|
+
const at = visibleKeys.indexOf(from);
|
|
6426
|
+
if (!node || at < 0 || e.shiftKey) return null;
|
|
6427
|
+
const isOpen = openSet.has(from);
|
|
6428
|
+
switch (e.key) {
|
|
6429
|
+
case "ArrowDown":
|
|
6430
|
+
return visibleKeys[at + 1] ?? from;
|
|
6431
|
+
case "ArrowUp":
|
|
6432
|
+
return visibleKeys[at - 1] ?? headKeys[0] ?? from;
|
|
6433
|
+
case "Home":
|
|
6434
|
+
return visibleKeys[0];
|
|
6435
|
+
case "End":
|
|
6436
|
+
return visibleKeys[visibleKeys.length - 1];
|
|
6437
|
+
case "ArrowRight":
|
|
6438
|
+
if (!node.children.length) return from;
|
|
6439
|
+
if (!isOpen) {
|
|
6440
|
+
toggleOpen(node.id);
|
|
6441
|
+
return from;
|
|
6442
|
+
}
|
|
6443
|
+
return visibleKeys[at + 1] ?? from;
|
|
6444
|
+
case "ArrowLeft":
|
|
6445
|
+
if (node.children.length && isOpen) {
|
|
6446
|
+
toggleOpen(node.id);
|
|
6447
|
+
return from;
|
|
6448
|
+
}
|
|
6449
|
+
return node.parent ? String(node.parent.id) : from;
|
|
6450
|
+
default:
|
|
6451
|
+
return null;
|
|
6452
|
+
}
|
|
6453
|
+
},
|
|
6454
|
+
// Enter and Space do what a click on the row does, onRowClick, else its Details (the second review, N8: on an
|
|
6455
|
+
// expandable table a click opened Details where Enter showed the rows); on a row a click does nothing on, its
|
|
6456
|
+
// selection, else its rows
|
|
6457
|
+
onActivate: (key, e) => {
|
|
6458
|
+
const node = nested?.byKey.get(key);
|
|
6459
|
+
if (!node) return;
|
|
6460
|
+
if (onRowClick) onRowClick(node.row, node.originalIdx);
|
|
6461
|
+
else if (canOpenByClick) toggleExpand(node.id);
|
|
6462
|
+
else if (selectable && boxOf(node.originalIdx, node.id)) toggleBox(node.originalIdx, node.id, e.shiftKey);
|
|
6463
|
+
else if (node.children.length) toggleOpen(node.id);
|
|
6464
|
+
}
|
|
6465
|
+
});
|
|
6466
|
+
const onTreeKeyDown = (e) => {
|
|
6467
|
+
if (e.target instanceof HTMLElement && e.target.parentElement === e.currentTarget) grid.onKeyDown(e);
|
|
6468
|
+
};
|
|
6469
|
+
const onHeadKeyDown = (e) => {
|
|
6470
|
+
if (e.defaultPrevented || e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return;
|
|
6471
|
+
const key = e.target instanceof HTMLElement ? fromGrid(e.target.getAttribute("data-grid-key")) : null;
|
|
6472
|
+
const at = key === null ? -1 : headKeys.indexOf(key);
|
|
6473
|
+
if (key === null || at < 0) return;
|
|
6474
|
+
let next;
|
|
6475
|
+
switch (e.key) {
|
|
6476
|
+
case "ArrowLeft":
|
|
6477
|
+
next = headKeys[at - 1] ?? key;
|
|
6478
|
+
break;
|
|
6479
|
+
case "ArrowRight":
|
|
6480
|
+
next = headKeys[at + 1] ?? key;
|
|
6481
|
+
break;
|
|
6482
|
+
case "Home":
|
|
6483
|
+
next = headKeys[0];
|
|
6484
|
+
break;
|
|
6485
|
+
case "End":
|
|
6486
|
+
next = headKeys[headKeys.length - 1];
|
|
6487
|
+
break;
|
|
6488
|
+
case "ArrowDown":
|
|
6489
|
+
next = visibleKeys[0] ?? key;
|
|
6490
|
+
break;
|
|
6491
|
+
case "ArrowUp":
|
|
6492
|
+
next = key;
|
|
6493
|
+
break;
|
|
6494
|
+
default:
|
|
6495
|
+
return;
|
|
6496
|
+
}
|
|
6497
|
+
e.preventDefault();
|
|
6498
|
+
setFocusKey(next);
|
|
6499
|
+
grid.focus(next);
|
|
6500
|
+
};
|
|
6501
|
+
const onHeadFocus = (e) => {
|
|
6502
|
+
const key = fromGrid(e.target.getAttribute("data-grid-key"));
|
|
6503
|
+
if (key !== null && headKeys.includes(key)) setFocusKey(key);
|
|
6504
|
+
};
|
|
6505
|
+
const selectAllRef = useRef(null);
|
|
6506
|
+
useLayoutEffect(() => {
|
|
6507
|
+
const input = selectAllRef.current;
|
|
6508
|
+
if (!input) return;
|
|
6509
|
+
if (nested) {
|
|
6510
|
+
input.setAttribute("data-grid-key", gridKey(`${HEAD_KEY}select`));
|
|
6511
|
+
input.tabIndex = !heldOuter && activeKey === `${HEAD_KEY}select` ? 0 : -1;
|
|
6512
|
+
} else if (input.hasAttribute("data-grid-key")) {
|
|
6513
|
+
input.removeAttribute("data-grid-key");
|
|
6514
|
+
input.removeAttribute("tabindex");
|
|
6515
|
+
}
|
|
6516
|
+
});
|
|
6517
|
+
const [rowsBody, setRowsBody] = useState(null);
|
|
6518
|
+
const [held] = useState(() => /* @__PURE__ */ new WeakMap());
|
|
6519
|
+
const stopRef = useRef("");
|
|
6520
|
+
const holding = useRef(null);
|
|
6521
|
+
const stopKey = heldOuter ? "" : activeKey;
|
|
6522
|
+
useLayoutEffect(() => {
|
|
6523
|
+
const was = stopRef.current;
|
|
6524
|
+
stopRef.current = stopKey;
|
|
6525
|
+
if (was === stopKey || !rowsBody || !holding.current) return;
|
|
6526
|
+
holding.current([...rowsOfKey(rowsBody, ownKey, was), ...rowsOfKey(rowsBody, ownKey, stopKey)]);
|
|
6527
|
+
}, [stopKey, rowsBody, ownKey]);
|
|
6528
|
+
const treeShown = !!nested && !isMobile;
|
|
6529
|
+
useLayoutEffect(() => {
|
|
6530
|
+
const body = rowsBody;
|
|
6531
|
+
if (!treeShown || !body) return;
|
|
6532
|
+
const ours = (el) => el.closest("table[role='treegrid']") === body.parentElement;
|
|
6533
|
+
const release = (el) => {
|
|
6534
|
+
const own = held.get(el) ?? "";
|
|
6535
|
+
held.delete(el);
|
|
6536
|
+
if (own === "") el.removeAttribute("tabindex");
|
|
6537
|
+
else el.setAttribute("tabindex", own);
|
|
6538
|
+
};
|
|
6539
|
+
const settle = (tr) => {
|
|
6540
|
+
const grid2 = tr.getAttribute("data-grid-key");
|
|
6541
|
+
const owner = grid2?.startsWith(ownKey) ? grid2.slice(ownKey.length) : tr.getAttribute("data-panel-of");
|
|
6542
|
+
if (owner === null) return;
|
|
6543
|
+
if (owner === stopRef.current) {
|
|
6544
|
+
for (const el of Array.from(tr.querySelectorAll("[tabindex]"))) if (held.has(el)) release(el);
|
|
6545
|
+
return;
|
|
6546
|
+
}
|
|
6547
|
+
for (const el of Array.from(tr.querySelectorAll(FOCUSABLE))) {
|
|
6548
|
+
if (!ours(el)) continue;
|
|
6549
|
+
if (!held.has(el) || el.getAttribute("tabindex") !== "-1") held.set(el, el.getAttribute("tabindex") ?? "");
|
|
6550
|
+
if (el.getAttribute("tabindex") !== "-1") el.setAttribute("tabindex", "-1");
|
|
6551
|
+
}
|
|
6552
|
+
};
|
|
6553
|
+
const touched = (records) => {
|
|
6554
|
+
const rows = /* @__PURE__ */ new Set();
|
|
6555
|
+
for (const r of records) {
|
|
6556
|
+
const target = r.target instanceof Element ? r.target : r.target.parentElement;
|
|
6557
|
+
if (!target) continue;
|
|
6558
|
+
if (r.type === "attributes" && r.attributeName === "tabindex" && target instanceof HTMLElement && held.has(target)) held.set(target, target.getAttribute("tabindex") ?? "");
|
|
6559
|
+
if (target === body) {
|
|
6560
|
+
r.addedNodes.forEach((n) => {
|
|
6561
|
+
if (n instanceof Element) rows.add(n);
|
|
6562
|
+
});
|
|
6563
|
+
continue;
|
|
6564
|
+
}
|
|
6565
|
+
if (target.parentElement === body) {
|
|
6566
|
+
if (r.type === "childList") rows.add(target);
|
|
6567
|
+
continue;
|
|
6568
|
+
}
|
|
6569
|
+
let tr = target.closest("tr");
|
|
6570
|
+
while (tr && tr.parentElement !== body) tr = tr.parentElement?.closest("tr") ?? null;
|
|
6571
|
+
if (tr) rows.add(tr);
|
|
6572
|
+
}
|
|
6573
|
+
return rows;
|
|
6574
|
+
};
|
|
6575
|
+
const sync = (also = []) => {
|
|
6576
|
+
const rows = touched(observer.takeRecords());
|
|
6577
|
+
for (const tr of also) rows.add(tr);
|
|
6578
|
+
for (const tr of rows) settle(tr);
|
|
6579
|
+
observer.takeRecords();
|
|
6580
|
+
};
|
|
6581
|
+
const observer = new MutationObserver((records) => {
|
|
6582
|
+
for (const tr of touched(records)) settle(tr);
|
|
6583
|
+
observer.takeRecords();
|
|
6584
|
+
});
|
|
6585
|
+
observer.observe(body, { childList: true, subtree: true, attributes: true, attributeFilter: ["tabindex", "disabled"] });
|
|
6586
|
+
holding.current = sync;
|
|
6587
|
+
sync(Array.from(body.rows));
|
|
6588
|
+
return () => {
|
|
6589
|
+
observer.disconnect();
|
|
6590
|
+
holding.current = null;
|
|
6591
|
+
for (const el of Array.from(body.querySelectorAll("[tabindex]"))) if (held.has(el)) release(el);
|
|
6592
|
+
};
|
|
6593
|
+
}, [treeShown, rowsBody, held, ownKey]);
|
|
6594
|
+
const focusIn = useRef(null);
|
|
6595
|
+
useLayoutEffect(() => {
|
|
6596
|
+
const was = focusIn.current;
|
|
6597
|
+
if (!nested || was === null || visibleSet.has(was)) return;
|
|
6598
|
+
focusIn.current = null;
|
|
6599
|
+
const now = document.activeElement;
|
|
6600
|
+
if (now && now !== document.body && now.isConnected) return;
|
|
6601
|
+
grid.focus(activeKey);
|
|
6602
|
+
});
|
|
6603
|
+
const onRowsBlur = (e) => {
|
|
6604
|
+
if (e.target.isConnected && !e.currentTarget.contains(e.relatedTarget)) focusIn.current = null;
|
|
6605
|
+
};
|
|
6606
|
+
const onRowFocus = (e) => {
|
|
6607
|
+
const key = fromGrid(e.currentTarget.getAttribute("data-grid-key")) ?? e.currentTarget.getAttribute("data-panel-of");
|
|
6608
|
+
if (key === null) return;
|
|
6609
|
+
focusIn.current = key;
|
|
6610
|
+
setFocusKey(key);
|
|
6611
|
+
};
|
|
6069
6612
|
const shownBefore = useRef(/* @__PURE__ */ new Set());
|
|
6070
6613
|
const pendingScroll = useRef(null);
|
|
6071
6614
|
const scrollFrame = useRef(0);
|
|
@@ -6079,6 +6622,32 @@ function Table({
|
|
|
6079
6622
|
row.scrollIntoView({ block: "nearest" });
|
|
6080
6623
|
});
|
|
6081
6624
|
}, [rootRef]);
|
|
6625
|
+
const addressRow = (key) => {
|
|
6626
|
+
let top = key;
|
|
6627
|
+
let waits = false;
|
|
6628
|
+
const above = [];
|
|
6629
|
+
for (let p = nested?.byKey.get(key)?.parent; p; p = p.parent) above.unshift(p);
|
|
6630
|
+
if (above.length) {
|
|
6631
|
+
top = String(above[0].id);
|
|
6632
|
+
const shut = above.filter((p) => !openSet.has(String(p.id)));
|
|
6633
|
+
if (shut.length && openControlled) {
|
|
6634
|
+
onOpenParentsChange?.([...open, ...shut.map((p) => p.id)]);
|
|
6635
|
+
pendingScroll.current = key;
|
|
6636
|
+
waits = true;
|
|
6637
|
+
}
|
|
6638
|
+
}
|
|
6639
|
+
if (pager) {
|
|
6640
|
+
const position = sortedAll.findIndex((r) => String(idOf(r.row, r.originalIdx)) === top);
|
|
6641
|
+
if (position >= 0 && (position < drawnStart || position >= drawnStart + drawn.length)) {
|
|
6642
|
+
pendingScroll.current = key;
|
|
6643
|
+
pager.setPage(Math.floor(position / pager.pageSize) + 1);
|
|
6644
|
+
return;
|
|
6645
|
+
}
|
|
6646
|
+
}
|
|
6647
|
+
if (waits) return;
|
|
6648
|
+
scrollToRow(key);
|
|
6649
|
+
};
|
|
6650
|
+
const awaitedRow = useRef(null);
|
|
6082
6651
|
useEffect(() => {
|
|
6083
6652
|
const now = new Set(expanded.map(String));
|
|
6084
6653
|
const added = [...now].filter((k) => !shownBefore.current.has(k) && k !== openedHere.current);
|
|
@@ -6087,22 +6656,25 @@ function Table({
|
|
|
6087
6656
|
if (!expandControlled) return;
|
|
6088
6657
|
const key = added[added.length - 1];
|
|
6089
6658
|
if (key === void 0) return;
|
|
6090
|
-
if (
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
pendingScroll.current = key;
|
|
6094
|
-
pager.setPage(Math.floor(position / pager.pageSize) + 1);
|
|
6095
|
-
return;
|
|
6096
|
-
}
|
|
6659
|
+
if (tree && !tree.byKey.has(key)) {
|
|
6660
|
+
awaitedRow.current = key;
|
|
6661
|
+
return;
|
|
6097
6662
|
}
|
|
6098
|
-
|
|
6663
|
+
awaitedRow.current = null;
|
|
6664
|
+
addressRow(key);
|
|
6099
6665
|
}, [expandedKey]);
|
|
6666
|
+
useEffect(() => {
|
|
6667
|
+
const key = awaitedRow.current;
|
|
6668
|
+
if (key === null || !tree?.byKey.has(key)) return;
|
|
6669
|
+
awaitedRow.current = null;
|
|
6670
|
+
addressRow(key);
|
|
6671
|
+
}, [tree]);
|
|
6100
6672
|
useEffect(() => {
|
|
6101
6673
|
const key = pendingScroll.current;
|
|
6102
|
-
if (!key || !drawn.some((r) => String(idOf(r.row, r.originalIdx)) === key)) return;
|
|
6674
|
+
if (!key || !(nested ? visibleSet.has(key) : drawn.some((r) => String(idOf(r.row, r.originalIdx)) === key))) return;
|
|
6103
6675
|
pendingScroll.current = null;
|
|
6104
6676
|
scrollToRow(key);
|
|
6105
|
-
}, [drawnStart, drawn.length, scrollToRow]);
|
|
6677
|
+
}, [drawnStart, drawn.length, visibleKeys.length, scrollToRow]);
|
|
6106
6678
|
const cardHeading = title ? /* @__PURE__ */ jsx(TableHeading, { title, description, actions, titleId, descriptionId, inset: false }) : null;
|
|
6107
6679
|
const titledCards = (body) => /* @__PURE__ */ jsxs("div", { ref: listRoot, "data-ds-list": "", "data-gs": "table", className: cn("flex flex-col", listClass), onFocus: noteFocus, onBlur: forgetFocus, children: [
|
|
6108
6680
|
cardHeading,
|
|
@@ -6146,7 +6718,7 @@ function Table({
|
|
|
6146
6718
|
if (!row) return;
|
|
6147
6719
|
const controls = Array.from(row.querySelectorAll(FOCUSABLE));
|
|
6148
6720
|
const same = was.control === null ? null : controls.find((el) => (el.getAttribute("aria-labelledby") ?? el.getAttribute("aria-label") ?? el.textContent) === was.control);
|
|
6149
|
-
(same ?? (row.tabIndex >= 0 ? row : controls[0]))?.focus({ preventScroll: true });
|
|
6721
|
+
(same ?? (row.tabIndex >= 0 || row.hasAttribute("data-grid-key") ? row : controls[0]))?.focus({ preventScroll: true });
|
|
6150
6722
|
}, [isMobile, rootRef]);
|
|
6151
6723
|
if (isMobile) {
|
|
6152
6724
|
if (loading && data.length === 0) {
|
|
@@ -6167,289 +6739,363 @@ function Table({
|
|
|
6167
6739
|
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
6740
|
loading && data.length > 0 && /* @__PURE__ */ jsx(RefreshLine, { className: "inset-x-[4px] rounded-full" }),
|
|
6169
6741
|
selectable && /* @__PURE__ */ jsx("span", { hidden: true, id: `${headingId}-select`, children: "Select" }),
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6742
|
+
nested && /* @__PURE__ */ jsx("span", { hidden: true, id: `${headingId}-under`, children: "under" }),
|
|
6743
|
+
nested && /* @__PURE__ */ jsx("span", { hidden: true, id: `${headingId}-rows-under`, children: "Rows under" }),
|
|
6744
|
+
nested ? drawn.map((d) => treeCards(nested.roots[d.originalIdx])) : drawn.map(({ row, originalIdx }) => cardOf(row, originalIdx))
|
|
6745
|
+
] }) }) });
|
|
6746
|
+
return withControl(title ? titledCards(cards) : cards);
|
|
6747
|
+
}
|
|
6748
|
+
function cardOf(row, originalIdx, node) {
|
|
6749
|
+
const id = node ? node.id : idOf(row, originalIdx);
|
|
6750
|
+
const box = boxOf(originalIdx, id);
|
|
6751
|
+
const isSelected = !!box?.checked;
|
|
6752
|
+
const opens = !!expandable && !!renderExpanded;
|
|
6753
|
+
const isExpanded = opens && expandedSet.has(String(id));
|
|
6754
|
+
const toggleCard = (card) => {
|
|
6755
|
+
const closing = isExpanded;
|
|
6756
|
+
const inDetail = closing && card.querySelector("[data-card-detail]")?.contains(document.activeElement);
|
|
6757
|
+
toggleExpand(id);
|
|
6758
|
+
if (inDetail) card.querySelector("[data-card-toggle]")?.focus();
|
|
6759
|
+
};
|
|
6760
|
+
const under = node?.children.length ?? 0;
|
|
6761
|
+
const isOpen = under > 0 && openSet.has(String(id));
|
|
6762
|
+
return /* @__PURE__ */ jsxs(
|
|
6763
|
+
"div",
|
|
6764
|
+
{
|
|
6765
|
+
"data-row": "",
|
|
6766
|
+
...marksOf(row, originalIdx, id),
|
|
6767
|
+
className: cn(
|
|
6768
|
+
"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
6769
|
+
"rounded-[var(--ds-radius-md)] bg-[var(--ds-bg-surface)]",
|
|
6770
|
+
"p-ds-4 space-y-ds-3",
|
|
6771
|
+
// selected is chosen, not active (D2): the accent border, never the halo
|
|
6772
|
+
isSelected && "border-[var(--ds-accent-ink)]",
|
|
6773
|
+
onRowClick && ["cursor-pointer hover:bg-[var(--ds-bg-muted)]", FOCUS_RING],
|
|
6774
|
+
// with no onRowClick a tap on the card opens and closes it, as a click on the row does; the toggle is the
|
|
6775
|
+
// keyboard's way
|
|
6776
|
+
!onRowClick && canOpenByClick && "cursor-pointer"
|
|
6777
|
+
),
|
|
6778
|
+
onClick: onRowClick ? (e) => {
|
|
6779
|
+
if (clickIsCard(e)) onRowClick(row, originalIdx);
|
|
6780
|
+
} : canOpenByClick ? (e) => {
|
|
6781
|
+
if (clickIsCard(e)) toggleCard(e.currentTarget);
|
|
6782
|
+
} : void 0,
|
|
6783
|
+
tabIndex: onRowClick ? 0 : void 0,
|
|
6784
|
+
onKeyDown: onRowClick ? (e) => {
|
|
6785
|
+
if (e.target !== e.currentTarget) return;
|
|
6786
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
6787
|
+
e.preventDefault();
|
|
6788
|
+
onRowClick(row, originalIdx);
|
|
6789
|
+
}
|
|
6790
|
+
} : void 0,
|
|
6791
|
+
children: [
|
|
6792
|
+
selectable && box && // "Select" and the row's name, as in the table (T15); a parent with some of its rows chosen is mixed
|
|
6793
|
+
/* @__PURE__ */ jsx(Checkbox, { checked: isSelected, indeterminate: box.mixed, onChange: (_, { shiftKey: shiftKey2 }) => toggleBox(originalIdx, id, shiftKey2), "aria-labelledby": nameIndex >= 0 ? `${headingId}-select ${headingId}-card-name-${idPart(id)}` : `${headingId}-select` }),
|
|
6794
|
+
columns.map((col, c) => /* @__PURE__ */ jsxs("div", { className: "flex justify-between gap-ds-2 text-sm", children: [
|
|
6795
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-[var(--ds-text-secondary)] font-medium text-xs uppercase tracking-wider", children: col.header }),
|
|
6796
|
+
/* @__PURE__ */ jsx(CardValue, { value: row[col.key], id: lead + c === nameIndex ? `${headingId}-card-name-${idPart(id)}` : void 0 })
|
|
6797
|
+
] }, col.key)),
|
|
6798
|
+
under > 0 && // item 14: the rows under it, shown and hidden as the Details are, with how many and the row's name
|
|
6799
|
+
/* @__PURE__ */ jsx("div", { className: "pt-ds-1", children: /* @__PURE__ */ jsxs(
|
|
6800
|
+
"button",
|
|
6801
|
+
{
|
|
6802
|
+
type: "button",
|
|
6803
|
+
"data-card-rows-toggle": "",
|
|
6804
|
+
"aria-expanded": isOpen,
|
|
6805
|
+
"aria-labelledby": nameIndex >= 0 ? `${headingId}-card-rows-${idPart(id)} ${headingId}-under ${headingId}-card-name-${idPart(id)}` : `${headingId}-card-rows-${idPart(id)}`,
|
|
6806
|
+
onClick: (e) => {
|
|
6807
|
+
e.stopPropagation();
|
|
6808
|
+
toggleOpen(id);
|
|
6809
|
+
},
|
|
6810
|
+
className: CARD_TOGGLE,
|
|
6811
|
+
children: [
|
|
6812
|
+
/* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 12, className: cn("transition-transform duration-[var(--ds-transition-speed)]", isOpen && "rotate-90") }),
|
|
6813
|
+
/* @__PURE__ */ jsx("span", { id: `${headingId}-card-rows-${idPart(id)}`, children: `${isOpen ? "Hide" : "Show"} ${under} ${under === 1 ? "row" : "rows"}` })
|
|
6814
|
+
]
|
|
6815
|
+
}
|
|
6816
|
+
) }),
|
|
6817
|
+
opens && // Alert's disclosure: a button that says whether it is open, at the card's foot, the detail below it, so
|
|
6818
|
+
// the control the user pressed stays where it was. Its name carries the row's (T15).
|
|
6819
|
+
/* @__PURE__ */ jsxs("div", { className: "pt-ds-1", children: [
|
|
6820
|
+
/* @__PURE__ */ jsxs(
|
|
6821
|
+
"button",
|
|
6822
|
+
{
|
|
6823
|
+
type: "button",
|
|
6824
|
+
"data-card-toggle": "",
|
|
6825
|
+
"aria-expanded": isExpanded,
|
|
6826
|
+
...nameIndex >= 0 ? { "aria-labelledby": `${headingId}-card-toggle-${idPart(id)} ${headingId}-card-name-${idPart(id)}` } : {},
|
|
6827
|
+
onClick: (e) => {
|
|
6828
|
+
e.stopPropagation();
|
|
6829
|
+
toggleCard(e.currentTarget.closest("[data-row]"));
|
|
6830
|
+
},
|
|
6831
|
+
className: CARD_TOGGLE,
|
|
6832
|
+
children: [
|
|
6833
|
+
/* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 12, className: cn("transition-transform duration-[var(--ds-transition-speed)]", isExpanded && "rotate-90") }),
|
|
6834
|
+
/* @__PURE__ */ jsx("span", { id: `${headingId}-card-toggle-${idPart(id)}`, children: isExpanded ? "Hide details" : "Show details" })
|
|
6835
|
+
]
|
|
6208
6836
|
}
|
|
6209
|
-
|
|
6210
|
-
children:
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6837
|
+
),
|
|
6838
|
+
isExpanded && /* @__PURE__ */ jsx("div", { "data-card-detail": "", className: "mt-ds-3 pt-ds-3 border-t-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] text-sm text-[var(--ds-text-secondary)]", children: /* @__PURE__ */ jsx(PanelContent, { children: renderExpanded(row, originalIdx) }) })
|
|
6839
|
+
] })
|
|
6840
|
+
]
|
|
6841
|
+
},
|
|
6842
|
+
String(id)
|
|
6843
|
+
);
|
|
6844
|
+
}
|
|
6845
|
+
function treeCards(node) {
|
|
6846
|
+
const key = String(node.id);
|
|
6847
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
6848
|
+
cardOf(node.row, node.originalIdx, node),
|
|
6849
|
+
node.children.length > 0 && openSet.has(key) && /* @__PURE__ */ jsx(
|
|
6850
|
+
"div",
|
|
6851
|
+
{
|
|
6852
|
+
role: "group",
|
|
6853
|
+
"data-card-rows": "",
|
|
6854
|
+
"aria-labelledby": nameIndex >= 0 ? `${headingId}-rows-under ${headingId}-card-name-${idPart(node.id)}` : `${headingId}-rows-under`,
|
|
6855
|
+
className: "ml-ds-5 pl-ds-3 border-l-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] flex flex-col gap-ds-3",
|
|
6856
|
+
children: (childOrder?.get(key) ?? node.children).map(treeCards)
|
|
6857
|
+
}
|
|
6858
|
+
)
|
|
6859
|
+
] }, key);
|
|
6860
|
+
}
|
|
6861
|
+
const cellCount = columns.length + lead + trail;
|
|
6862
|
+
const bodyRows = visible ? visible.map((v) => ({ row: v.node.row, originalIdx: v.node.originalIdx, tree: v })) : drawn;
|
|
6863
|
+
const table = (
|
|
6864
|
+
// a tree table is a treegrid (item 14): its rows have levels, and the arrow keys move between them
|
|
6865
|
+
/* @__PURE__ */ jsxs("table", { ref: tableRef, role: nested ? "treegrid" : void 0, "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: [
|
|
6866
|
+
/* @__PURE__ */ jsx("thead", { className: cn("bg-[var(--ds-bg-muted)]", stickyHeader && "sticky top-0 z-10"), onKeyDown: nested ? onHeadKeyDown : void 0, onFocus: nested ? onHeadFocus : void 0, 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: [
|
|
6867
|
+
selectable && // data-ds-select-all: the selection's own control, where a BulkActionBar's Clear selection sends focus
|
|
6868
|
+
/* @__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(
|
|
6869
|
+
Checkbox,
|
|
6870
|
+
{
|
|
6871
|
+
ref: selectAllRef,
|
|
6872
|
+
checked: allSelected,
|
|
6873
|
+
indeterminate: someSelected,
|
|
6874
|
+
onChange: toggleAll,
|
|
6875
|
+
"aria-labelledby": `${headingId}-select-all`
|
|
6876
|
+
}
|
|
6877
|
+
) }),
|
|
6878
|
+
expandable && !trail && /* @__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) }),
|
|
6879
|
+
columns.map((col, c) => {
|
|
6880
|
+
const isSortable = sortsBy(col);
|
|
6881
|
+
const isActiveSort = sortKey === col.key && !!sortDir && (pageSorts || unsortable !== col.key);
|
|
6882
|
+
const headerKind = kindOf2(col);
|
|
6883
|
+
const headerAlign = col.align ?? (headerKind === "number" ? "right" : "left");
|
|
6884
|
+
const shrink = (headerKind === "number" || headerKind === "date") && !col.maxWidth;
|
|
6885
|
+
const style = { maxWidth: col.maxWidth, width: col.width, minWidth: col.minWidth, ...pinStyle(lead + c, cellCount) };
|
|
6886
|
+
return /* @__PURE__ */ jsx(
|
|
6887
|
+
"th",
|
|
6888
|
+
{
|
|
6889
|
+
"aria-sort": isSortable && isActiveSort ? sortDir === "asc" ? "ascending" : "descending" : void 0,
|
|
6890
|
+
className: cn(
|
|
6891
|
+
density === "compact" ? "px-ds-3 py-ds-2" : "px-ds-4 py-ds-3",
|
|
6892
|
+
shrink && "w-px whitespace-nowrap",
|
|
6893
|
+
"font-[var(--ds-weight-heading)] text-[var(--ds-text-secondary)]",
|
|
6894
|
+
"text-xs uppercase tracking-wider",
|
|
6895
|
+
headerAlign === "right" ? "text-right" : headerAlign === "center" ? "text-center" : "text-left"
|
|
6896
|
+
),
|
|
6897
|
+
style,
|
|
6898
|
+
children: isSortable ? (
|
|
6899
|
+
// A47: a button with the column's name, reached with Tab and pressed with Enter or Space
|
|
6220
6900
|
/* @__PURE__ */ jsxs(
|
|
6221
6901
|
"button",
|
|
6222
6902
|
{
|
|
6223
6903
|
type: "button",
|
|
6224
|
-
|
|
6225
|
-
"
|
|
6226
|
-
...nameIndex >= 0 ? { "aria-labelledby": `${headingId}-card-toggle-${idPart(id)} ${headingId}-card-name-${idPart(id)}` } : {},
|
|
6227
|
-
onClick: (e) => {
|
|
6228
|
-
e.stopPropagation();
|
|
6229
|
-
toggleCard(e.currentTarget.closest("[data-row]"));
|
|
6230
|
-
},
|
|
6904
|
+
onClick: () => handleSort(col.key),
|
|
6905
|
+
...nested ? { "data-grid-key": gridKey(`${HEAD_KEY}${col.key}`), tabIndex: heldOuter ? -1 : grid.tabIndexOf(`${HEAD_KEY}${col.key}`) } : {},
|
|
6231
6906
|
className: cn(
|
|
6232
|
-
|
|
6233
|
-
"
|
|
6234
|
-
"
|
|
6235
|
-
|
|
6236
|
-
|
|
6907
|
+
"inline-flex items-center gap-ds-1 uppercase tracking-wider cursor-pointer select-none",
|
|
6908
|
+
"[font:inherit] text-inherit hover:text-[var(--ds-text-primary)]",
|
|
6909
|
+
"rounded-[var(--ds-radius-sm)]",
|
|
6910
|
+
// in a right-aligned column the indicator goes before the label, so the label ends where the
|
|
6911
|
+
// column's values end; the sorted column's label in full colour (the look check, 14 October).
|
|
6912
|
+
// Set at the line's top, not its baseline: reversed, the button takes its baseline from the
|
|
6913
|
+
// indicator, which has no text, and stood 2 px above the other headers' labels
|
|
6914
|
+
headerAlign === "right" && "flex-row-reverse",
|
|
6915
|
+
"align-top",
|
|
6916
|
+
isActiveSort && "text-[var(--ds-text-primary)]",
|
|
6237
6917
|
FOCUS_RING
|
|
6238
6918
|
),
|
|
6239
6919
|
children: [
|
|
6240
|
-
|
|
6241
|
-
/* @__PURE__ */ jsx(
|
|
6920
|
+
col.header,
|
|
6921
|
+
/* @__PURE__ */ jsx(SortIndicator, { sorted: isActiveSort ? sortDir : false })
|
|
6242
6922
|
]
|
|
6243
6923
|
}
|
|
6244
|
-
)
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
)
|
|
6251
|
-
})
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
|
|
6924
|
+
)
|
|
6925
|
+
) : /* @__PURE__ */ jsx("span", { className: "inline-flex items-center gap-ds-1", children: col.header })
|
|
6926
|
+
},
|
|
6927
|
+
col.key
|
|
6928
|
+
);
|
|
6929
|
+
}),
|
|
6930
|
+
trail > 0 && /* @__PURE__ */ jsx("th", { className: cn("w-8", density === "compact" ? "px-ds-1 py-ds-2" : "px-ds-2 py-ds-3"), style: pinStyle(cellCount - 1, cellCount) })
|
|
6931
|
+
] }) }),
|
|
6932
|
+
/* @__PURE__ */ jsx("tbody", { ref: nested ? setRowsBody : void 0, onKeyDown: nested ? onTreeKeyDown : void 0, onBlur: nested ? onRowsBlur : void 0, children: /* @__PURE__ */ jsx(RowsCtx, { value: true, children: loading && data.length === 0 ? (
|
|
6933
|
+
// the rows' shape on a first load (item 16), each cell's bar where its text will be; the rows are hidden
|
|
6934
|
+
// from a screen reader, which hears the status beside the table
|
|
6935
|
+
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: [
|
|
6936
|
+
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" }) }),
|
|
6937
|
+
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") }),
|
|
6938
|
+
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))
|
|
6939
|
+
] }, `skeleton-${r}`))
|
|
6940
|
+
) : data.length === 0 && emptyState ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
|
|
6941
|
+
"td",
|
|
6261
6942
|
{
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
"aria-labelledby": `${headingId}-select-all`
|
|
6943
|
+
colSpan: cellCount,
|
|
6944
|
+
className: "px-ds-4 py-ds-10 text-center text-sm text-[var(--ds-text-muted)]",
|
|
6945
|
+
children: emptyState
|
|
6266
6946
|
}
|
|
6267
|
-
) }),
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
const
|
|
6271
|
-
const
|
|
6272
|
-
const
|
|
6273
|
-
const
|
|
6274
|
-
const
|
|
6275
|
-
const
|
|
6276
|
-
|
|
6277
|
-
"
|
|
6278
|
-
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
children: isSortable ? (
|
|
6289
|
-
// A47: a button with the column's name, reached with Tab and pressed with Enter or Space
|
|
6290
|
-
/* @__PURE__ */ jsxs(
|
|
6291
|
-
"button",
|
|
6292
|
-
{
|
|
6293
|
-
type: "button",
|
|
6294
|
-
onClick: () => handleSort(col.key),
|
|
6295
|
-
className: cn(
|
|
6296
|
-
"inline-flex items-center gap-ds-1 uppercase tracking-wider cursor-pointer select-none",
|
|
6297
|
-
"[font:inherit] text-inherit hover:text-[var(--ds-text-primary)]",
|
|
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)]",
|
|
6306
|
-
FOCUS_RING
|
|
6307
|
-
),
|
|
6308
|
-
children: [
|
|
6309
|
-
col.header,
|
|
6310
|
-
/* @__PURE__ */ jsx(SortIndicator, { sorted: isActiveSort ? sortDir : false })
|
|
6311
|
-
]
|
|
6312
|
-
}
|
|
6313
|
-
)
|
|
6314
|
-
) : /* @__PURE__ */ jsx("span", { className: "inline-flex items-center gap-ds-1", children: col.header })
|
|
6315
|
-
},
|
|
6316
|
-
col.key
|
|
6317
|
-
);
|
|
6318
|
-
})
|
|
6319
|
-
] }) }),
|
|
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(
|
|
6329
|
-
"td",
|
|
6330
|
-
{
|
|
6331
|
-
colSpan: cellCount,
|
|
6332
|
-
className: "px-ds-4 py-ds-10 text-center text-sm text-[var(--ds-text-muted)]",
|
|
6333
|
-
children: emptyState
|
|
6334
|
-
}
|
|
6335
|
-
) }) : drawn.map(({ row, originalIdx }, i) => {
|
|
6336
|
-
const isSelected = selectedSet.has(originalIdx);
|
|
6337
|
-
const id = idOf(row, originalIdx);
|
|
6338
|
-
const isExpanded = expandedSet.has(String(id));
|
|
6339
|
-
const clickable = !!onRowClick || canOpenByClick;
|
|
6340
|
-
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
6341
|
-
/* @__PURE__ */ jsxs(
|
|
6342
|
-
"tr",
|
|
6343
|
-
{
|
|
6344
|
-
...marksOf(row, originalIdx),
|
|
6345
|
-
className: cn(
|
|
6346
|
-
// an opened row's divider is under its panel (A6)
|
|
6347
|
-
!(expandable && isExpanded && renderExpanded) && "border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] last:border-b-0",
|
|
6348
|
-
// the row's background and its tint change together, so its pinned cells and the rest fade as one
|
|
6349
|
-
// (roots.css registers --gs-row-tint as a colour so it can)
|
|
6350
|
-
"transition-[background-color,--gs-row-tint]",
|
|
6351
|
-
// the row's tint, as a variable too, so its pinned cells draw it over their solid ground (A35)
|
|
6352
|
-
isSelected ? "bg-[var(--ds-accent-subtle)] [--gs-row-tint:var(--ds-accent-subtle)]" : striped && i % 2 === 1 ? "bg-[var(--ds-bg-muted)]/50 [--gs-row-tint:color-mix(in_oklab,var(--ds-bg-muted)_50%,transparent)]" : "hover:bg-[var(--ds-bg-muted)] hover:[--gs-row-tint:var(--ds-bg-muted)]",
|
|
6353
|
-
clickable && "cursor-pointer",
|
|
6354
|
-
// an outline inside the row, clear of the frame's rounded corners (D8): it shows over the pinned
|
|
6355
|
-
// cells, whose solid ground hid the inset shadow the row drew before (the review of 30 September)
|
|
6356
|
-
onRowClick && FOCUS_INSET
|
|
6357
|
-
),
|
|
6358
|
-
onClick: clickable ? (e) => {
|
|
6359
|
-
if (!clickIsRows(e)) return;
|
|
6360
|
-
if (onRowClick) onRowClick(row, originalIdx);
|
|
6361
|
-
else toggleExpand(id);
|
|
6362
|
-
} : void 0,
|
|
6363
|
-
tabIndex: onRowClick ? 0 : void 0,
|
|
6364
|
-
onKeyDown: onRowClick ? (e) => {
|
|
6365
|
-
if (e.target !== e.currentTarget) return;
|
|
6366
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
6367
|
-
e.preventDefault();
|
|
6368
|
-
onRowClick(row, originalIdx);
|
|
6369
|
-
}
|
|
6370
|
-
} : void 0,
|
|
6371
|
-
children: [
|
|
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(
|
|
6374
|
-
"button",
|
|
6375
|
-
{
|
|
6376
|
-
type: "button",
|
|
6377
|
-
onClick: () => toggleExpand(id),
|
|
6378
|
-
className: cn("text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] cursor-pointer", FOCUS_RING),
|
|
6379
|
-
"aria-expanded": isExpanded,
|
|
6380
|
-
...nameIndex >= 0 ? { "aria-labelledby": `${headingId}-details ${headingId}-name-${idPart(id)}` } : { "aria-label": "Details" },
|
|
6381
|
-
children: /* @__PURE__ */ jsx(
|
|
6382
|
-
Icon,
|
|
6383
|
-
{
|
|
6384
|
-
name: "chevron-right",
|
|
6385
|
-
size: 14,
|
|
6386
|
-
className: cn("transition-transform", isExpanded && "rotate-90")
|
|
6387
|
-
}
|
|
6388
|
-
)
|
|
6389
|
-
}
|
|
6390
|
-
) }) }),
|
|
6391
|
-
columns.map((col, c) => {
|
|
6392
|
-
const truncLines = col.truncate === true ? 1 : col.truncate ? col.truncate.lines : 0;
|
|
6393
|
-
const kind = kindOf2(col);
|
|
6394
|
-
const alignClass = col.align ? col.align === "right" ? "text-right" : col.align === "center" ? "text-center" : "text-left" : kind === "number" ? "text-right" : "text-left";
|
|
6395
|
-
const cellContent = row[col.key];
|
|
6396
|
-
const shrink = (kind === "number" || kind === "date") && !col.maxWidth;
|
|
6397
|
-
const whole2 = !kind && renderedKinds.has(col.key);
|
|
6398
|
-
let inner;
|
|
6399
|
-
if (truncLines > 0) {
|
|
6400
|
-
inner = /* @__PURE__ */ jsx(CutCell, { lines: truncLines, children: cellContent });
|
|
6401
|
-
} else if (kind === "email") {
|
|
6402
|
-
inner = /* @__PURE__ */ jsx(CutEmail, { children: cellContent });
|
|
6403
|
-
} else {
|
|
6404
|
-
inner = cellContent;
|
|
6405
|
-
}
|
|
6406
|
-
const align = col.align ?? (kind === "number" ? "right" : "left");
|
|
6407
|
-
if (align !== "left" && cellContent !== null && cellContent !== void 0 && typeof cellContent !== "string" && typeof cellContent !== "number") {
|
|
6408
|
-
inner = /* @__PURE__ */ jsx("div", { className: cn("flex items-center", align === "center" ? "justify-center" : "justify-end"), children: inner });
|
|
6409
|
-
}
|
|
6410
|
-
return /* @__PURE__ */ jsx(
|
|
6411
|
-
"td",
|
|
6412
|
-
{
|
|
6413
|
-
id: lead > 0 && lead + c === nameIndex ? `${headingId}-name-${idPart(id)}` : void 0,
|
|
6414
|
-
"data-col": col.key,
|
|
6415
|
-
className: cn(
|
|
6416
|
-
density === "compact" ? "px-ds-3 py-ds-2" : "px-ds-4 py-ds-3",
|
|
6417
|
-
"text-[var(--ds-text-primary)]",
|
|
6418
|
-
alignClass,
|
|
6419
|
-
shrink && "w-px whitespace-nowrap",
|
|
6420
|
-
whole2 && "whitespace-nowrap",
|
|
6421
|
-
kind === "identifier" && "[overflow-wrap:anywhere]",
|
|
6422
|
-
pinFocus(lead + c, cellCount)
|
|
6423
|
-
),
|
|
6424
|
-
style: col.maxWidth || col.width || col.minWidth || c + lead < pinnedStart || c >= columns.length - endCount ? { maxWidth: col.maxWidth, width: col.width, minWidth: col.minWidth, ...pinStyle(lead + c, cellCount) } : void 0,
|
|
6425
|
-
children: inner
|
|
6426
|
-
},
|
|
6427
|
-
col.key
|
|
6428
|
-
);
|
|
6429
|
-
})
|
|
6430
|
-
]
|
|
6431
|
-
}
|
|
6432
|
-
),
|
|
6433
|
-
expandable && isExpanded && renderExpanded && /* @__PURE__ */ jsx("tr", { className: "border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] last:border-b-0", children: /* @__PURE__ */ jsx(
|
|
6434
|
-
"td",
|
|
6947
|
+
) }) : bodyRows.map(({ row, originalIdx, tree: place }, i) => {
|
|
6948
|
+
const node = place?.node;
|
|
6949
|
+
const id = node ? node.id : idOf(row, originalIdx);
|
|
6950
|
+
const box = boxOf(originalIdx, id);
|
|
6951
|
+
const isSelected = !!box?.checked;
|
|
6952
|
+
const isExpanded = expandedSet.has(String(id));
|
|
6953
|
+
const clickable = !!onRowClick || canOpenByClick;
|
|
6954
|
+
const isParent = !!node?.children.length;
|
|
6955
|
+
const isOpen = isParent && openSet.has(String(id));
|
|
6956
|
+
const treeRow = place ? {
|
|
6957
|
+
"aria-level": place.node.level,
|
|
6958
|
+
"aria-setsize": place.size,
|
|
6959
|
+
"aria-posinset": place.pos,
|
|
6960
|
+
"aria-expanded": isParent ? isOpen : void 0,
|
|
6961
|
+
"data-grid-key": gridKey(String(id)),
|
|
6962
|
+
onFocus: onRowFocus
|
|
6963
|
+
} : {};
|
|
6964
|
+
const nameRef = node ? `${headingId}-tree-name-${idPart(id)}` : `${headingId}-name-${idPart(id)}`;
|
|
6965
|
+
const detailsAt = trail ? cellCount - 1 : selectable ? 1 : 0;
|
|
6966
|
+
const details = expandable && /* @__PURE__ */ jsx("td", { className: cn("w-8", density === "compact" ? "px-ds-1 py-ds-2" : "px-ds-2 py-ds-3", pinFocus(detailsAt, cellCount)), style: pinStyle(detailsAt, cellCount), children: /* @__PURE__ */ jsx(AutoTooltip, { content: "Details", children: /* @__PURE__ */ jsx(
|
|
6967
|
+
"button",
|
|
6435
6968
|
{
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6969
|
+
type: "button",
|
|
6970
|
+
onClick: () => toggleExpand(id),
|
|
6971
|
+
className: cn("text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] cursor-pointer", FOCUS_RING),
|
|
6972
|
+
"aria-expanded": isExpanded,
|
|
6973
|
+
...nameIndex >= 0 ? { "aria-labelledby": `${headingId}-details ${nameRef}` } : { "aria-label": "Details" },
|
|
6439
6974
|
children: /* @__PURE__ */ jsx(
|
|
6440
|
-
|
|
6975
|
+
Icon,
|
|
6441
6976
|
{
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
children: /* @__PURE__ */ jsx(PanelContent, { children: renderExpanded(row, originalIdx) })
|
|
6977
|
+
name: "chevron-right",
|
|
6978
|
+
size: 14,
|
|
6979
|
+
className: cn("transition-transform", isExpanded && "rotate-90")
|
|
6446
6980
|
}
|
|
6447
6981
|
)
|
|
6448
6982
|
}
|
|
6449
|
-
) })
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6983
|
+
) }) });
|
|
6984
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
6985
|
+
/* @__PURE__ */ jsxs(
|
|
6986
|
+
"tr",
|
|
6987
|
+
{
|
|
6988
|
+
...marksOf(row, originalIdx, id),
|
|
6989
|
+
...treeRow,
|
|
6990
|
+
className: cn(
|
|
6991
|
+
// an opened row's divider is under its panel (A6)
|
|
6992
|
+
!(expandable && isExpanded && renderExpanded) && "border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] last:border-b-0",
|
|
6993
|
+
// the row's background and its tint change together, so its pinned cells and the rest fade as one
|
|
6994
|
+
// (roots.css registers --gs-row-tint as a colour so it can)
|
|
6995
|
+
"transition-[background-color,--gs-row-tint]",
|
|
6996
|
+
// the row's tint, as a variable too, so its pinned cells draw it over their solid ground (A35)
|
|
6997
|
+
isSelected ? "bg-[var(--ds-accent-subtle)] [--gs-row-tint:var(--ds-accent-subtle)]" : striped && i % 2 === 1 ? "bg-[var(--ds-bg-muted)]/50 [--gs-row-tint:color-mix(in_oklab,var(--ds-bg-muted)_50%,transparent)]" : "hover:bg-[var(--ds-bg-muted)] hover:[--gs-row-tint:var(--ds-bg-muted)]",
|
|
6998
|
+
clickable && "cursor-pointer",
|
|
6999
|
+
// an outline inside the row, clear of the frame's rounded corners (D8): it shows over the pinned
|
|
7000
|
+
// cells, whose solid ground hid the inset shadow the row drew before (the review of 30 September)
|
|
7001
|
+
(onRowClick || place) && FOCUS_INSET
|
|
7002
|
+
),
|
|
7003
|
+
onClick: clickable ? (e) => {
|
|
7004
|
+
if (!clickIsRows(e)) return;
|
|
7005
|
+
if (onRowClick) onRowClick(row, originalIdx);
|
|
7006
|
+
else toggleExpand(id);
|
|
7007
|
+
} : void 0,
|
|
7008
|
+
tabIndex: place ? heldOuter ? -1 : grid.tabIndexOf(String(id)) : onRowClick ? 0 : void 0,
|
|
7009
|
+
onKeyDown: onRowClick && !place ? (e) => {
|
|
7010
|
+
if (e.target !== e.currentTarget) return;
|
|
7011
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
7012
|
+
e.preventDefault();
|
|
7013
|
+
onRowClick(row, originalIdx);
|
|
7014
|
+
}
|
|
7015
|
+
} : void 0,
|
|
7016
|
+
children: [
|
|
7017
|
+
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: box && /* @__PURE__ */ jsx(Checkbox, { checked: isSelected, indeterminate: box.mixed, onChange: (_, { shiftKey: shiftKey2 }) => toggleBox(originalIdx, id, shiftKey2), "aria-labelledby": nameIndex >= 0 ? `${headingId}-select ${nameRef}` : `${headingId}-select` }) }),
|
|
7018
|
+
!trail && details,
|
|
7019
|
+
columns.map((col, c) => {
|
|
7020
|
+
const truncLines = col.truncate === true ? 1 : col.truncate ? col.truncate.lines : 0;
|
|
7021
|
+
const kind = kindOf2(col);
|
|
7022
|
+
const alignClass = col.align ? col.align === "right" ? "text-right" : col.align === "center" ? "text-center" : "text-left" : kind === "number" ? "text-right" : "text-left";
|
|
7023
|
+
const cellContent = row[col.key];
|
|
7024
|
+
const shrink = (kind === "number" || kind === "date") && !col.maxWidth;
|
|
7025
|
+
const whole2 = !kind && renderedKinds.has(col.key);
|
|
7026
|
+
let inner;
|
|
7027
|
+
if (truncLines > 0) {
|
|
7028
|
+
inner = /* @__PURE__ */ jsx(CutCell, { lines: truncLines, children: cellContent });
|
|
7029
|
+
} else if (kind === "email") {
|
|
7030
|
+
inner = /* @__PURE__ */ jsx(CutEmail, { children: cellContent });
|
|
7031
|
+
} else {
|
|
7032
|
+
inner = cellContent;
|
|
7033
|
+
}
|
|
7034
|
+
const align = col.align ?? (kind === "number" ? "right" : "left");
|
|
7035
|
+
if (align !== "left" && cellContent !== null && cellContent !== void 0 && typeof cellContent !== "string" && typeof cellContent !== "number") {
|
|
7036
|
+
inner = /* @__PURE__ */ jsx("div", { className: cn("flex items-center", align === "center" ? "justify-center" : "justify-end"), children: inner });
|
|
7037
|
+
}
|
|
7038
|
+
if (node && c === 0) {
|
|
7039
|
+
const nameId = nameRef;
|
|
7040
|
+
const under = node.children.length;
|
|
7041
|
+
inner = /* @__PURE__ */ jsxs("div", { "data-tree-indent": "", className: cn("flex items-center gap-ds-2", align === "center" ? "justify-center" : align === "right" && "justify-end"), style: node.level > 1 ? { paddingLeft: `calc(var(--ds-space-3) * ${node.level - 1})` } : void 0, children: [
|
|
7042
|
+
isParent ? (
|
|
7043
|
+
// named by its own words and then the row's name, which it points to: the cell's text stays the name
|
|
7044
|
+
/* @__PURE__ */ jsx("button", { type: "button", tabIndex: -1, "data-tree-toggle": "", id: `${nameId}-toggle`, "aria-label": `${isOpen ? "Hide" : "Show"} ${under} ${under === 1 ? "row" : "rows"} under`, "aria-labelledby": `${nameId}-toggle ${nameId}`, className: TREE_TOGGLE, onClick: (e) => {
|
|
7045
|
+
toggleOpen(id);
|
|
7046
|
+
e.currentTarget.closest("tr")?.focus();
|
|
7047
|
+
}, children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14, className: cn("transition-transform", isOpen && "rotate-90") }) })
|
|
7048
|
+
) : /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "shrink-0 w-4 h-4" }),
|
|
7049
|
+
/* @__PURE__ */ jsx("div", { id: nameId, className: "min-w-0", children: inner })
|
|
7050
|
+
] });
|
|
7051
|
+
}
|
|
7052
|
+
return /* @__PURE__ */ jsx(
|
|
7053
|
+
"td",
|
|
7054
|
+
{
|
|
7055
|
+
id: !node && lead > 0 && lead + c === nameIndex ? `${headingId}-name-${idPart(id)}` : void 0,
|
|
7056
|
+
"data-col": col.key,
|
|
7057
|
+
className: cn(
|
|
7058
|
+
density === "compact" ? "px-ds-3 py-ds-2" : "px-ds-4 py-ds-3",
|
|
7059
|
+
"text-[var(--ds-text-primary)]",
|
|
7060
|
+
alignClass,
|
|
7061
|
+
shrink && "w-px whitespace-nowrap",
|
|
7062
|
+
whole2 && "whitespace-nowrap",
|
|
7063
|
+
kind === "identifier" && "[overflow-wrap:anywhere]",
|
|
7064
|
+
pinFocus(lead + c, cellCount)
|
|
7065
|
+
),
|
|
7066
|
+
style: col.maxWidth || col.width || col.minWidth || c + lead < pinnedStart || c >= columns.length - endColumns ? { maxWidth: col.maxWidth, width: col.width, minWidth: col.minWidth, ...pinStyle(lead + c, cellCount) } : void 0,
|
|
7067
|
+
children: inner
|
|
7068
|
+
},
|
|
7069
|
+
col.key
|
|
7070
|
+
);
|
|
7071
|
+
}),
|
|
7072
|
+
trail > 0 && details
|
|
7073
|
+
]
|
|
7074
|
+
}
|
|
7075
|
+
),
|
|
7076
|
+
expandable && isExpanded && renderExpanded && // in a tree table the panel's controls join its row's in the Tab order, focus in it makes its row the
|
|
7077
|
+
// stop, and the panel is at its row's level, so a screen reader never places it a level apart (item 14)
|
|
7078
|
+
/* @__PURE__ */ jsx("tr", { "data-panel-of": place ? String(id) : void 0, "aria-level": place ? place.node.level : void 0, onFocus: place ? onRowFocus : void 0, className: "border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] last:border-b-0", children: /* @__PURE__ */ jsx(
|
|
7079
|
+
"td",
|
|
7080
|
+
{
|
|
7081
|
+
colSpan: cellCount,
|
|
7082
|
+
className: cn("py-ds-4 text-sm text-[var(--ds-text-primary)]", !pins.panel && (density === "compact" ? "px-ds-3" : "px-ds-4")),
|
|
7083
|
+
style: pins.panel ? { paddingLeft: pins.panel[0], paddingRight: pins.panel[1] } : void 0,
|
|
7084
|
+
children: /* @__PURE__ */ jsx(
|
|
7085
|
+
"div",
|
|
7086
|
+
{
|
|
7087
|
+
"data-row-panel": "",
|
|
7088
|
+
className: "sticky",
|
|
7089
|
+
style: pins.panel ? { left: pins.panel[0], maxWidth: pins.frame ? pins.frame - pins.panel[0] - pins.panel[1] : void 0 } : { left: 0 },
|
|
7090
|
+
children: place ? /* @__PURE__ */ jsx(TreeHeldCtx, { value: String(id) !== stopKey, children: /* @__PURE__ */ jsx(PanelContent, { children: renderExpanded(row, originalIdx) }) }) : /* @__PURE__ */ jsx(PanelContent, { children: renderExpanded(row, originalIdx) })
|
|
7091
|
+
}
|
|
7092
|
+
)
|
|
7093
|
+
}
|
|
7094
|
+
) })
|
|
7095
|
+
] }, String(id));
|
|
7096
|
+
}) }) })
|
|
7097
|
+
] })
|
|
7098
|
+
);
|
|
6453
7099
|
const region = scrollable || regionFocused ? { tabIndex: 0, role: "region", ...title ? { "aria-labelledby": titleId } : { "aria-label": ariaLabel ?? "Table" } } : {};
|
|
6454
7100
|
return withControl(
|
|
6455
7101
|
/* @__PURE__ */ jsxs(
|
|
@@ -6465,7 +7111,7 @@ function Table({
|
|
|
6465
7111
|
loading && data.length > 0 && /* @__PURE__ */ jsx(RefreshLine, { className: "inset-x-0 rounded-t-[inherit]" }),
|
|
6466
7112
|
loading && data.length === 0 && /* @__PURE__ */ jsx("span", { role: "status", className: "sr-only", children: LOADING_LABEL }),
|
|
6467
7113
|
title && /* @__PURE__ */ jsx(TableHeading, { title, description, actions, titleId, descriptionId, inset: true }),
|
|
6468
|
-
selectable && /* @__PURE__ */ jsx("span", { hidden: true, id: `${headingId}-select-all`, children: "Select all rows shown" }),
|
|
7114
|
+
selectable && /* @__PURE__ */ jsx("span", { hidden: true, id: `${headingId}-select-all`, children: nested ? pager ? "Select all rows on this page" : "Select all rows" : "Select all rows shown" }),
|
|
6469
7115
|
selectable && /* @__PURE__ */ jsx("span", { hidden: true, id: `${headingId}-select`, children: "Select" }),
|
|
6470
7116
|
expandable && /* @__PURE__ */ jsx("span", { hidden: true, id: `${headingId}-details`, children: "Details" }),
|
|
6471
7117
|
/* @__PURE__ */ jsx(
|
|
@@ -6491,266 +7137,32 @@ function Table({
|
|
|
6491
7137
|
)
|
|
6492
7138
|
);
|
|
6493
7139
|
}
|
|
6494
|
-
function optionsKeyForFit(options) {
|
|
6495
|
-
return options.map((o) => `${o.value}:${o.label}`).join("|");
|
|
6496
|
-
}
|
|
6497
|
-
var sizes2 = {
|
|
6498
|
-
xs: "text-xs px-ds-2",
|
|
6499
|
-
sm: "text-xs px-ds-3",
|
|
6500
|
-
md: "text-sm px-ds-3",
|
|
6501
|
-
lg: "text-base px-ds-3"
|
|
6502
|
-
};
|
|
6503
|
-
var containerPadding = {
|
|
6504
|
-
xs: "p-[2px] gap-[2px]",
|
|
6505
|
-
sm: "p-ds-1 gap-ds-0.5",
|
|
6506
|
-
md: "p-ds-1 gap-ds-0.5",
|
|
6507
|
-
lg: "p-ds-1 gap-ds-0.5"
|
|
6508
|
-
};
|
|
6509
|
-
var indicatorInset = {
|
|
6510
|
-
xs: "2px",
|
|
6511
|
-
sm: "4px",
|
|
6512
|
-
md: "4px",
|
|
6513
|
-
lg: "4px"
|
|
6514
|
-
};
|
|
6515
|
-
function segmentRadius(inset, bordered) {
|
|
6516
|
-
return `max(var(--ds-radius-sm), calc(var(--ds-radius-md) - ${inset}${bordered ? " - var(--ds-border-width)" : ""}))`;
|
|
6517
|
-
}
|
|
6518
|
-
function SegmentedControl({
|
|
6519
|
-
value,
|
|
6520
|
-
onChange: onChangeProp,
|
|
6521
|
-
options,
|
|
6522
|
-
size: sizeProp,
|
|
6523
|
-
variant = "default",
|
|
6524
|
-
fullWidth = false,
|
|
6525
|
-
onHoverChange,
|
|
6526
|
-
className,
|
|
6527
|
-
"aria-label": ariaLabel,
|
|
6528
|
-
maxOptions = 6,
|
|
6529
|
-
...wiring
|
|
6530
|
-
}) {
|
|
6531
|
-
const onChange = useReportedChange(onChangeProp, value);
|
|
6532
|
-
const contextSize = useContext(ControlSizeContext);
|
|
6533
|
-
const control = useFieldControl(wiring);
|
|
6534
|
-
const named = !ariaLabel && control.labelId ? { "aria-labelledby": control.labelId } : {};
|
|
6535
|
-
const size = sizeProp ?? contextSize ?? "md";
|
|
6536
|
-
const containerRef = useRef(null);
|
|
6537
|
-
const [indicator, setIndicator] = useState({ left: 0, width: 0 });
|
|
6538
|
-
const parentRef = useRef(null);
|
|
6539
|
-
const neededRef = useRef(0);
|
|
6540
|
-
const [overflows, setOverflows] = useState(false);
|
|
6541
|
-
const measureFit = useCallback(() => {
|
|
6542
|
-
const row = containerRef.current;
|
|
6543
|
-
if (row) {
|
|
6544
|
-
parentRef.current = row.parentElement;
|
|
6545
|
-
if (row.scrollWidth > 0) neededRef.current = row.scrollWidth;
|
|
6546
|
-
}
|
|
6547
|
-
const parent = parentRef.current;
|
|
6548
|
-
const needed = neededRef.current;
|
|
6549
|
-
if (!parent || !needed) return;
|
|
6550
|
-
const style = getComputedStyle(parent);
|
|
6551
|
-
const available = parent.clientWidth - (parseFloat(style.paddingLeft) || 0) - (parseFloat(style.paddingRight) || 0);
|
|
6552
|
-
if (available <= 0) return;
|
|
6553
|
-
setOverflows((prev) => prev ? needed > available - 8 : needed > available);
|
|
6554
|
-
}, []);
|
|
6555
|
-
useLayoutEffect(() => {
|
|
6556
|
-
measureFit();
|
|
6557
|
-
const parent = parentRef.current;
|
|
6558
|
-
if (!parent || typeof ResizeObserver === "undefined") return;
|
|
6559
|
-
const observer = new ResizeObserver(measureFit);
|
|
6560
|
-
observer.observe(parent);
|
|
6561
|
-
return () => observer.disconnect();
|
|
6562
|
-
}, [measureFit, optionsKeyForFit(options)]);
|
|
6563
|
-
const collapsed = options.length > maxOptions || overflows;
|
|
6564
|
-
const updateIndicator = useCallback(() => {
|
|
6565
|
-
if (!containerRef.current) return;
|
|
6566
|
-
const active = containerRef.current.querySelector("[data-active='true']");
|
|
6567
|
-
if (active) {
|
|
6568
|
-
setIndicator({
|
|
6569
|
-
left: active.offsetLeft,
|
|
6570
|
-
width: active.offsetWidth
|
|
6571
|
-
});
|
|
6572
|
-
}
|
|
6573
|
-
}, []);
|
|
6574
|
-
const optionsKey = options.map((o) => `${o.value}:${o.label}`).join("|");
|
|
6575
|
-
useLayoutEffect(() => {
|
|
6576
|
-
updateIndicator();
|
|
6577
|
-
}, [value, optionsKey, updateIndicator]);
|
|
6578
|
-
useEffect(() => {
|
|
6579
|
-
const fonts = document.fonts;
|
|
6580
|
-
if (!fonts?.ready) return;
|
|
6581
|
-
let live = true;
|
|
6582
|
-
fonts.ready.then(() => {
|
|
6583
|
-
if (live) updateIndicator();
|
|
6584
|
-
});
|
|
6585
|
-
return () => {
|
|
6586
|
-
live = false;
|
|
6587
|
-
};
|
|
6588
|
-
}, [updateIndicator]);
|
|
6589
|
-
const [animate, setAnimate] = useState(false);
|
|
6590
|
-
const select = useCallback((v) => {
|
|
6591
|
-
setAnimate(true);
|
|
6592
|
-
onChange(v);
|
|
6593
|
-
}, [onChange]);
|
|
6594
|
-
useLayoutEffect(() => {
|
|
6595
|
-
if (collapsed || !containerRef.current || typeof ResizeObserver === "undefined") return;
|
|
6596
|
-
const observer = new ResizeObserver(updateIndicator);
|
|
6597
|
-
observer.observe(containerRef.current);
|
|
6598
|
-
containerRef.current.querySelectorAll("button").forEach((b) => observer.observe(b));
|
|
6599
|
-
return () => observer.disconnect();
|
|
6600
|
-
}, [updateIndicator, optionsKey, collapsed]);
|
|
6601
|
-
const containerHeight = {
|
|
6602
|
-
xs: "h-ds-6",
|
|
6603
|
-
sm: "h-[var(--ds-control-height-sm)]",
|
|
6604
|
-
md: "h-[var(--ds-control-height-md)]",
|
|
6605
|
-
lg: "h-[var(--ds-control-height-lg)]"
|
|
6606
|
-
};
|
|
6607
|
-
const tabStop = rovingTabStop(options, (o) => o.value === value, (o) => !!o.disabled);
|
|
6608
|
-
const handleKeyDown = (e) => {
|
|
6609
|
-
const enabled = options.filter((o) => !o.disabled);
|
|
6610
|
-
if (enabled.length === 0) return;
|
|
6611
|
-
const idx = Math.max(0, enabled.findIndex((o) => o.value === value));
|
|
6612
|
-
let next = null;
|
|
6613
|
-
if (e.key === "ArrowRight" || e.key === "ArrowDown") next = (idx + 1) % enabled.length;
|
|
6614
|
-
else if (e.key === "ArrowLeft" || e.key === "ArrowUp") next = (idx - 1 + enabled.length) % enabled.length;
|
|
6615
|
-
else if (e.key === "Home") next = 0;
|
|
6616
|
-
else if (e.key === "End") next = enabled.length - 1;
|
|
6617
|
-
if (next === null) return;
|
|
6618
|
-
e.preventDefault();
|
|
6619
|
-
select(enabled[next].value);
|
|
6620
|
-
const buttons = containerRef.current?.querySelectorAll('[role="radio"]');
|
|
6621
|
-
buttons?.forEach((b) => {
|
|
6622
|
-
if (b.dataset.value === enabled[next].value) b.focus();
|
|
6623
|
-
});
|
|
6624
|
-
};
|
|
6625
|
-
if (collapsed) {
|
|
6626
|
-
return /* @__PURE__ */ jsx(
|
|
6627
|
-
Dropdown,
|
|
6628
|
-
{
|
|
6629
|
-
"aria-label": ariaLabel,
|
|
6630
|
-
...wiring,
|
|
6631
|
-
size: size === "md" || size === "lg" ? "md" : "sm",
|
|
6632
|
-
options: options.filter((o) => !o.disabled).map((o) => ({ id: o.value, label: o.label })),
|
|
6633
|
-
value,
|
|
6634
|
-
onChange: (v) => onChange(v),
|
|
6635
|
-
className: cn("inline-block", fullWidth ? "w-full" : "w-auto", className)
|
|
6636
|
-
}
|
|
6637
|
-
);
|
|
6638
|
-
}
|
|
6639
|
-
return /* @__PURE__ */ jsxs(
|
|
6640
|
-
"div",
|
|
6641
|
-
{
|
|
6642
|
-
ref: containerRef,
|
|
6643
|
-
role: "radiogroup",
|
|
6644
|
-
id: control.id,
|
|
6645
|
-
"aria-label": ariaLabel,
|
|
6646
|
-
...named,
|
|
6647
|
-
"aria-describedby": control.describedBy,
|
|
6648
|
-
"aria-invalid": control.invalid || void 0,
|
|
6649
|
-
"aria-required": control.required || void 0,
|
|
6650
|
-
onKeyDown: handleKeyDown,
|
|
6651
|
-
className: cn(
|
|
6652
|
-
"relative items-center",
|
|
6653
|
-
// Sprint 25.14 A21: in a Field's column a track that isn't full width keeps its own width; w-fit, not self-start,
|
|
6654
|
-
// so a row or a centred column still aligns it (the review of 30 September)
|
|
6655
|
-
fullWidth ? "flex w-full" : "inline-flex w-fit",
|
|
6656
|
-
containerPadding[size],
|
|
6657
|
-
containerHeight[size],
|
|
6658
|
-
"bg-[var(--ds-bg-muted)]",
|
|
6659
|
-
// The owner's review of 1 October 2026: the frame's corner is a field's, so the two change together with the
|
|
6660
|
-
// theme's radius; the segments inside sit concentric with it (SEGMENT_RADIUS)
|
|
6661
|
-
"rounded-[var(--ds-radius-md)]",
|
|
6662
|
-
// The frame's edge is a button's: each segment is a labelled button, so the frame isn't what identifies the
|
|
6663
|
-
// control, and WCAG 1.4.11 asks no 3:1 of it
|
|
6664
|
-
variant === "default" && "border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
6665
|
-
control.invalid && "border-[length:var(--ds-border-width)] border-[var(--ds-status-error)]",
|
|
6666
|
-
className
|
|
6667
|
-
),
|
|
6668
|
-
style: { "--ds-segment-radius": segmentRadius(indicatorInset[size], variant === "default" || !!control.invalid) },
|
|
6669
|
-
children: [
|
|
6670
|
-
/* @__PURE__ */ jsx(
|
|
6671
|
-
"div",
|
|
6672
|
-
{
|
|
6673
|
-
className: cn(
|
|
6674
|
-
"absolute rounded-[var(--ds-segment-radius)]",
|
|
6675
|
-
"bg-[var(--ds-bg-surface)]",
|
|
6676
|
-
// The selected segment is a kind of button, so it takes a secondary button's surface and edge, as the frame
|
|
6677
|
-
// takes a button's edge (the owner, 3 October 2026: the 3:1 strong edge it kept from Sprint 25.14 drew the
|
|
6678
|
-
// darker outline 25.19 took off the fields). It shows its state as the raised surface on the muted track, with
|
|
6679
|
-
// the default variant's shadow and its label's stronger colour. While its segment has keyboard focus the shadow
|
|
6680
|
-
// steps aside, as a button's does, so the segment's outline sits clear (Sprint 30, D7)
|
|
6681
|
-
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
6682
|
-
variant === "default" && "shadow-[var(--ds-shadow-sm)]",
|
|
6683
|
-
"[[role=radiogroup]:has([aria-checked=true]:focus-visible)_&]:shadow-none",
|
|
6684
|
-
"transition-all motion-reduce:transition-none"
|
|
6685
|
-
),
|
|
6686
|
-
"data-animate": animate ? "true" : "false",
|
|
6687
|
-
style: {
|
|
6688
|
-
left: indicator.left,
|
|
6689
|
-
width: indicator.width,
|
|
6690
|
-
top: indicatorInset[size],
|
|
6691
|
-
bottom: indicatorInset[size],
|
|
6692
|
-
transitionDuration: animate ? "var(--ds-transition-speed)" : "0ms",
|
|
6693
|
-
transitionTimingFunction: "var(--ds-transition-ease)"
|
|
6694
|
-
}
|
|
6695
|
-
}
|
|
6696
|
-
),
|
|
6697
|
-
options.map((opt, i) => /* @__PURE__ */ jsx(
|
|
6698
|
-
"button",
|
|
6699
|
-
{
|
|
6700
|
-
type: "button",
|
|
6701
|
-
role: "radio",
|
|
6702
|
-
"aria-checked": opt.value === value,
|
|
6703
|
-
"data-active": opt.value === value,
|
|
6704
|
-
"data-value": opt.value,
|
|
6705
|
-
tabIndex: i === tabStop ? 0 : -1,
|
|
6706
|
-
disabled: opt.disabled,
|
|
6707
|
-
onClick: () => !opt.disabled && select(opt.value),
|
|
6708
|
-
onMouseEnter: onHoverChange && !opt.disabled ? () => onHoverChange(opt.value) : void 0,
|
|
6709
|
-
onMouseLeave: onHoverChange ? () => onHoverChange(null) : void 0,
|
|
6710
|
-
className: cn(
|
|
6711
|
-
"relative z-10 inline-flex items-center justify-center self-stretch font-medium whitespace-nowrap",
|
|
6712
|
-
fullWidth && "flex-1",
|
|
6713
|
-
"rounded-[var(--ds-segment-radius)]",
|
|
6714
|
-
"transition-colors cursor-pointer",
|
|
6715
|
-
FOCUS_RING,
|
|
6716
|
-
sizes2[size],
|
|
6717
|
-
opt.value === value ? "text-[var(--ds-text-primary)]" : "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-secondary)]",
|
|
6718
|
-
opt.disabled && "opacity-disabled cursor-not-allowed"
|
|
6719
|
-
),
|
|
6720
|
-
children: opt.label
|
|
6721
|
-
},
|
|
6722
|
-
opt.value
|
|
6723
|
-
))
|
|
6724
|
-
]
|
|
6725
|
-
}
|
|
6726
|
-
);
|
|
6727
|
-
}
|
|
6728
7140
|
|
|
6729
7141
|
// ../../showcase/src/components/Calendar/event-colours.ts
|
|
6730
7142
|
function eventColours(category) {
|
|
6731
7143
|
const colour = category?.color;
|
|
6732
7144
|
if (colour === void 0 || colour === "accent" || colour === "var(--ds-accent-primary)") return ACCENT;
|
|
6733
|
-
if (colour === "neutral") return
|
|
6734
|
-
if (typeof colour === "number") return Number.isInteger(colour) && colour >= 1 ? supporting(colour) :
|
|
7145
|
+
if (colour === "neutral") return NEUTRAL2;
|
|
7146
|
+
if (typeof colour === "number") return Number.isInteger(colour) && colour >= 1 ? supporting(colour) : NEUTRAL2;
|
|
6735
7147
|
const named = SUPPORTING_TOKEN.exec(colour.trim());
|
|
6736
7148
|
if (named) return supporting(Number(named[1]));
|
|
6737
7149
|
const chart = CHART_TOKEN.exec(colour.trim());
|
|
6738
7150
|
if (chart) return Number(chart[1]) === 1 ? ACCENT : supporting(Number(chart[1]) - 1);
|
|
6739
|
-
return { ...
|
|
7151
|
+
return { ...NEUTRAL2, edge: colour };
|
|
6740
7152
|
}
|
|
6741
7153
|
var SUPPORTING_TOKEN = /^var\(\s*--ds-palette-(\d+)-[a-z-]+\s*\)$/;
|
|
6742
7154
|
var CHART_TOKEN = /^var\(\s*--ds-chart-(\d+)\s*\)$/;
|
|
6743
7155
|
var supporting = (n) => ({
|
|
6744
|
-
fill: `var(--ds-palette-${n}-bg, ${
|
|
6745
|
-
text: `var(--ds-palette-${n}-text, ${
|
|
6746
|
-
edge: `var(--ds-palette-${n}-chart, ${
|
|
7156
|
+
fill: `var(--ds-palette-${n}-bg, ${NEUTRAL2.fill})`,
|
|
7157
|
+
text: `var(--ds-palette-${n}-text, ${NEUTRAL2.text})`,
|
|
7158
|
+
edge: `var(--ds-palette-${n}-chart, ${NEUTRAL2.edge})`
|
|
6747
7159
|
});
|
|
6748
7160
|
var ACCENT = {
|
|
6749
7161
|
fill: "var(--ds-accent-bg, var(--ds-accent-subtle))",
|
|
6750
7162
|
text: "var(--ds-accent-text, var(--ds-text-primary))",
|
|
6751
7163
|
edge: "var(--ds-chart-1)"
|
|
6752
7164
|
};
|
|
6753
|
-
var
|
|
7165
|
+
var NEUTRAL2 = {
|
|
6754
7166
|
fill: "var(--ds-bg-muted)",
|
|
6755
7167
|
text: "var(--ds-text-primary)",
|
|
6756
7168
|
edge: "var(--ds-control-edge-strong)"
|
|
@@ -8849,8 +9261,10 @@ function ExpandableDescription({ children, className }) {
|
|
|
8849
9261
|
}
|
|
8850
9262
|
);
|
|
8851
9263
|
}
|
|
8852
|
-
function HorizontalLayout({ items, minItemWidth, className }) {
|
|
8853
|
-
|
|
9264
|
+
function HorizontalLayout({ items, minItemWidth, label, className }) {
|
|
9265
|
+
const [row, setRow] = useState(null);
|
|
9266
|
+
useKeyboardScroll(row, label, true, false, "x");
|
|
9267
|
+
return /* @__PURE__ */ jsx("div", { ref: setRow, "data-timeline-row": "", className: cn("relative flex items-start overflow-x-auto snap-x", FOCUS_INSET, className), children: items.map((item, i) => {
|
|
8854
9268
|
const isFirst = i === 0;
|
|
8855
9269
|
const isLast = i === items.length - 1;
|
|
8856
9270
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 shrink-0 flex-col items-center snap-start", style: { minWidth: minItemWidth }, children: [
|
|
@@ -8928,7 +9342,7 @@ function VerticalLayout({ items, className }) {
|
|
|
8928
9342
|
] })
|
|
8929
9343
|
] }, i)) });
|
|
8930
9344
|
}
|
|
8931
|
-
function Timeline({ items: allItems, orientation = "vertical", minItemWidth = 200, className, ref, pager }) {
|
|
9345
|
+
function Timeline({ items: allItems, orientation = "vertical", minItemWidth = 200, className, ref, pager, "aria-label": ariaLabel = "Timeline" }) {
|
|
8932
9346
|
useScrollsInside();
|
|
8933
9347
|
useWholeListCheck("Timeline", allItems.length, pager);
|
|
8934
9348
|
const items = pagerPart(allItems, pager);
|
|
@@ -8941,7 +9355,7 @@ function Timeline({ items: allItems, orientation = "vertical", minItemWidth = 20
|
|
|
8941
9355
|
}, [ref]);
|
|
8942
9356
|
const fits = width === 0 || width >= items.length * minItemWidth;
|
|
8943
9357
|
const horizontal = orientation === "horizontal" || orientation === "responsive" && fits;
|
|
8944
|
-
const list2 = /* @__PURE__ */ jsx("div", { ref: setRefs, "data-ds-list": "", "data-timeline-orientation": horizontal ? "horizontal" : "vertical", className: pager ? void 0 : className, children: /* @__PURE__ */ jsx(RowsCtx, { value: true, children: horizontal ? /* @__PURE__ */ jsx(HorizontalLayout, { items, minItemWidth }) : /* @__PURE__ */ jsx(VerticalLayout, { items }) }) });
|
|
9358
|
+
const list2 = /* @__PURE__ */ jsx("div", { ref: setRefs, "data-ds-list": "", "data-timeline-orientation": horizontal ? "horizontal" : "vertical", className: pager ? void 0 : className, children: /* @__PURE__ */ jsx(RowsCtx, { value: true, children: horizontal ? /* @__PURE__ */ jsx(HorizontalLayout, { items, minItemWidth, label: ariaLabel }) : /* @__PURE__ */ jsx(VerticalLayout, { items }) }) });
|
|
8945
9359
|
if (!pager) return list2;
|
|
8946
9360
|
return /* @__PURE__ */ jsxs("div", { "data-gs-paged": "", className: cn("flex flex-col min-w-0", className), children: [
|
|
8947
9361
|
list2,
|
|
@@ -12281,7 +12695,7 @@ function useScrollTrack(stopTab, enabled) {
|
|
|
12281
12695
|
};
|
|
12282
12696
|
}
|
|
12283
12697
|
var SCROLL_TRACK = "overflow-x-auto overflow-y-hidden [scrollbar-width:none] [&::-webkit-scrollbar]:hidden";
|
|
12284
|
-
function TabStrip({ overflow, fullWidth, track, className, children }) {
|
|
12698
|
+
function TabStrip({ overflow, fullWidth, track, label, className, children }) {
|
|
12285
12699
|
const scrolls = overflow === "scroll";
|
|
12286
12700
|
return /* @__PURE__ */ jsx("div", { className: cn("min-w-0 max-w-full", fullWidth && "w-full", className), children: /* @__PURE__ */ jsx(
|
|
12287
12701
|
"div",
|
|
@@ -12289,7 +12703,7 @@ function TabStrip({ overflow, fullWidth, track, className, children }) {
|
|
|
12289
12703
|
...scrolls ? track : {},
|
|
12290
12704
|
"data-gs-clip": scrolls ? void 0 : "",
|
|
12291
12705
|
className: cn("relative -m-[4px] p-[4px] scroll-px-[4px]", scrolls ? SCROLL_TRACK : "overflow-hidden"),
|
|
12292
|
-
children: /* @__PURE__ */ jsx("div", { role: "tablist", className: cn(trackClasses("horizontal"), scrolls ? "w-max min-w-full" : "w-full"), children })
|
|
12706
|
+
children: /* @__PURE__ */ jsx("div", { role: "tablist", "aria-label": label, className: cn(trackClasses("horizontal"), scrolls ? "w-max min-w-full" : "w-full"), children })
|
|
12293
12707
|
}
|
|
12294
12708
|
) });
|
|
12295
12709
|
}
|
|
@@ -12450,7 +12864,7 @@ function TabButton({
|
|
|
12450
12864
|
return btn;
|
|
12451
12865
|
}
|
|
12452
12866
|
function TabsList({ children, className }) {
|
|
12453
|
-
const { orientation, fullWidth, overflow, stopTab } = useTabsCtx();
|
|
12867
|
+
const { orientation, fullWidth, overflow, stopTab, label } = useTabsCtx();
|
|
12454
12868
|
const track = useScrollTrack(stopTab, orientation === "horizontal" && overflow === "scroll");
|
|
12455
12869
|
if (orientation === "vertical") {
|
|
12456
12870
|
return /* @__PURE__ */ jsx(
|
|
@@ -12458,12 +12872,13 @@ function TabsList({ children, className }) {
|
|
|
12458
12872
|
{
|
|
12459
12873
|
role: "tablist",
|
|
12460
12874
|
"aria-orientation": "vertical",
|
|
12875
|
+
"aria-label": label,
|
|
12461
12876
|
className: cn(trackClasses("vertical"), className),
|
|
12462
12877
|
children
|
|
12463
12878
|
}
|
|
12464
12879
|
);
|
|
12465
12880
|
}
|
|
12466
|
-
return /* @__PURE__ */ jsx(TabStrip, { overflow, fullWidth, track, className, children });
|
|
12881
|
+
return /* @__PURE__ */ jsx(TabStrip, { overflow, fullWidth, track, label, className, children });
|
|
12467
12882
|
}
|
|
12468
12883
|
function TabsTrigger({ value, children, count, icon, disabled, truncate, className }) {
|
|
12469
12884
|
const { activeTab, onTabChange, orientation, fullWidth, overflow, activation, stopTab, setFocusedTab } = useTabsCtx();
|
|
@@ -12510,6 +12925,7 @@ function TabsRoot(props) {
|
|
|
12510
12925
|
fullWidth = false,
|
|
12511
12926
|
overflow = "scroll",
|
|
12512
12927
|
activation = "automatic",
|
|
12928
|
+
"aria-label": ariaLabel,
|
|
12513
12929
|
className
|
|
12514
12930
|
} = props;
|
|
12515
12931
|
const isMobile = useBreakpoint("md");
|
|
@@ -12533,6 +12949,7 @@ function TabsRoot(props) {
|
|
|
12533
12949
|
options: tabs.filter((t) => !t.disabled).map((t) => ({ id: t.id, label: t.label, group: t.group })),
|
|
12534
12950
|
value: activeTab,
|
|
12535
12951
|
onChange: (v) => onTabChange(v),
|
|
12952
|
+
"aria-label": ariaLabel ?? "Contents",
|
|
12536
12953
|
className
|
|
12537
12954
|
}
|
|
12538
12955
|
) })
|
|
@@ -12544,6 +12961,7 @@ function TabsRoot(props) {
|
|
|
12544
12961
|
{
|
|
12545
12962
|
role: "tablist",
|
|
12546
12963
|
"aria-orientation": "vertical",
|
|
12964
|
+
"aria-label": ariaLabel,
|
|
12547
12965
|
className: cn(trackClasses("vertical"), className),
|
|
12548
12966
|
children: tabs.map((tab, i) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
12549
12967
|
tab.group && tab.group !== tabs[i - 1]?.group && /* @__PURE__ */ jsx(
|
|
@@ -12562,9 +12980,9 @@ function TabsRoot(props) {
|
|
|
12562
12980
|
}
|
|
12563
12981
|
);
|
|
12564
12982
|
}
|
|
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)) });
|
|
12983
|
+
return /* @__PURE__ */ jsx(TabStrip, { overflow: arrayOverflow, fullWidth, track, label: ariaLabel, 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)) });
|
|
12566
12984
|
}
|
|
12567
|
-
return /* @__PURE__ */ jsx(TabsContext.Provider, { value: { activeTab, onTabChange, orientation: effectiveOrientation, fullWidth, overflow, activation, stopTab, setFocusedTab }, children: /* @__PURE__ */ jsx("div", { className, children: props.children }) });
|
|
12985
|
+
return /* @__PURE__ */ jsx(TabsContext.Provider, { value: { activeTab, onTabChange, orientation: effectiveOrientation, fullWidth, overflow, activation, stopTab, setFocusedTab, label: ariaLabel }, children: /* @__PURE__ */ jsx("div", { className, children: props.children }) });
|
|
12568
12986
|
}
|
|
12569
12987
|
var Tabs = Object.assign(TabsRoot, {
|
|
12570
12988
|
List: TabsList,
|
|
@@ -12614,7 +13032,7 @@ function SettingsLayout({
|
|
|
12614
13032
|
const stickyTop = shell ? "var(--ds-sticky-offset, 0px)" : "calc(var(--ds-navbar-height) + var(--ds-sticky-offset, 0px))";
|
|
12615
13033
|
if (layout === "tabs") {
|
|
12616
13034
|
return /* @__PURE__ */ jsxs("div", { ref: rootRef, "data-settings-layout": "tabs", className: cn("flex flex-col gap-ds-6", className), children: [
|
|
12617
|
-
/* @__PURE__ */ jsx("nav", { "aria-label": ariaLabel, children: /* @__PURE__ */ jsx(Tabs, { orientation: "horizontal", mobile: "dropdown", tabs, activeTab: value, onTabChange: onChange }) }),
|
|
13035
|
+
/* @__PURE__ */ jsx("nav", { "aria-label": ariaLabel, children: /* @__PURE__ */ jsx(Tabs, { orientation: "horizontal", mobile: "dropdown", tabs, activeTab: value, onTabChange: onChange, "aria-label": ariaLabel }) }),
|
|
12618
13036
|
/* @__PURE__ */ jsx("div", { "data-settings-panel": "", className: PANEL_CLASSES, style: PANEL_STYLE, children })
|
|
12619
13037
|
] });
|
|
12620
13038
|
}
|
|
@@ -12636,7 +13054,7 @@ function SettingsLayout({
|
|
|
12636
13054
|
);
|
|
12637
13055
|
}
|
|
12638
13056
|
return /* @__PURE__ */ jsxs("div", { ref: rootRef, "data-settings-layout": "sidebar", className: cn("flex flex-row items-start gap-ds-8", className), children: [
|
|
12639
|
-
/* @__PURE__ */ jsx("nav", { "aria-label": ariaLabel, className: "sticky self-start shrink-0", style: { width: `${railWidth}px`, top: stickyTop }, children: /* @__PURE__ */ jsx(Tabs, { orientation: "vertical", tabs, activeTab: value, onTabChange: onChange, className: "w-full" }) }),
|
|
13057
|
+
/* @__PURE__ */ jsx("nav", { "aria-label": ariaLabel, className: "sticky self-start shrink-0", style: { width: `${railWidth}px`, top: stickyTop }, children: /* @__PURE__ */ jsx(Tabs, { orientation: "vertical", tabs, activeTab: value, onTabChange: onChange, "aria-label": ariaLabel, className: "w-full" }) }),
|
|
12640
13058
|
/* @__PURE__ */ jsx("div", { "data-settings-panel": "", className: cn("flex-1", PANEL_CLASSES), style: PANEL_STYLE, children })
|
|
12641
13059
|
] });
|
|
12642
13060
|
}
|
|
@@ -12842,11 +13260,12 @@ function ScrollArea({
|
|
|
12842
13260
|
className,
|
|
12843
13261
|
orientation = "vertical",
|
|
12844
13262
|
maxHeight,
|
|
12845
|
-
maxWidth
|
|
13263
|
+
maxWidth,
|
|
13264
|
+
"aria-label": ariaLabel = "Scrollable content"
|
|
12846
13265
|
}) {
|
|
12847
13266
|
const viewportRef = useRef(null);
|
|
12848
13267
|
const [viewport, setViewport] = useState(null);
|
|
12849
|
-
|
|
13268
|
+
useKeyboardScroll(viewport, ariaLabel, true, false, orientation === "horizontal" ? "x" : orientation === "both" ? "both" : "y");
|
|
12850
13269
|
const viewportRefs = useCallback((node) => {
|
|
12851
13270
|
viewportRef.current = node;
|
|
12852
13271
|
setViewport(node);
|
|
@@ -12941,7 +13360,9 @@ function ScrollArea({
|
|
|
12941
13360
|
ref: viewportRefs,
|
|
12942
13361
|
onScroll: updateThumbs,
|
|
12943
13362
|
className: cn(
|
|
12944
|
-
|
|
13363
|
+
// the frame's corners, so the inset ring follows them rather than being cut by them (as the Table's region)
|
|
13364
|
+
"h-full w-full scroll-p-[4px] rounded-[inherit]",
|
|
13365
|
+
FOCUS_INSET,
|
|
12945
13366
|
orientation === "vertical" && "overflow-y-auto overflow-x-hidden",
|
|
12946
13367
|
orientation === "horizontal" && "overflow-x-auto overflow-y-hidden",
|
|
12947
13368
|
orientation === "both" && "overflow-auto",
|
|
@@ -17889,6 +18310,6 @@ function DangerZone({ title = "Danger zone", description, children, className })
|
|
|
17889
18310
|
] });
|
|
17890
18311
|
}
|
|
17891
18312
|
|
|
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,
|
|
18313
|
+
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, 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 };
|
|
17893
18314
|
//# sourceMappingURL=index.js.map
|
|
17894
18315
|
//# sourceMappingURL=index.js.map
|