@tensor_1/react 2.47.0 → 2.49.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.
Files changed (204) hide show
  1. package/README.md +540 -2
  2. package/dist/{SchedulingCalendar-B6TakO2h.d.ts → SchedulingCalendar-WWyFL3Eo.d.ts} +51 -2
  3. package/dist/announce.d.ts +10 -0
  4. package/dist/announce.js +30 -0
  5. package/dist/chart-analytic.cjs +33 -25
  6. package/dist/chart-preset.cjs +23 -15
  7. package/dist/chart.cjs +23 -15
  8. package/dist/combobox-model.d.ts +10 -1
  9. package/dist/combobox-model.js +15 -0
  10. package/dist/command-palette-model.d.ts +44 -0
  11. package/dist/command-palette-model.js +36 -0
  12. package/dist/components/AccountMenu.d.ts +44 -0
  13. package/dist/components/AccountMenu.js +43 -0
  14. package/dist/components/AppShell.d.ts +45 -2
  15. package/dist/components/AppShell.js +116 -5
  16. package/dist/components/AuditLog.d.ts +128 -0
  17. package/dist/components/AuditLog.js +196 -0
  18. package/dist/components/BrandProfiles.js +4 -3
  19. package/dist/components/Breadcrumbs.d.ts +9 -2
  20. package/dist/components/Breadcrumbs.js +3 -2
  21. package/dist/components/Button.d.ts +12 -5
  22. package/dist/components/Button.js +7 -3
  23. package/dist/components/Card.d.ts +18 -1
  24. package/dist/components/Card.js +5 -1
  25. package/dist/components/ChangeHighlight.d.ts +30 -0
  26. package/dist/components/ChangeHighlight.js +21 -0
  27. package/dist/components/ChartCore.js +2 -1
  28. package/dist/components/Checkbox.d.ts +27 -1
  29. package/dist/components/Checkbox.js +31 -2
  30. package/dist/components/Chip.d.ts +7 -3
  31. package/dist/components/Chip.js +2 -2
  32. package/dist/components/CodeDisplay.d.ts +65 -0
  33. package/dist/components/CodeDisplay.js +124 -0
  34. package/dist/components/Combobox.d.ts +27 -6
  35. package/dist/components/Combobox.js +195 -58
  36. package/dist/components/CommandPalette.d.ts +36 -1
  37. package/dist/components/CommandPalette.js +254 -2
  38. package/dist/components/ContactCard.d.ts +66 -0
  39. package/dist/components/ContactCard.js +74 -0
  40. package/dist/components/Count.d.ts +24 -0
  41. package/dist/components/Count.js +32 -0
  42. package/dist/components/DashboardCanvas.js +14 -0
  43. package/dist/components/DataWorkspace.d.ts +167 -0
  44. package/dist/components/DataWorkspace.js +380 -0
  45. package/dist/components/DateFieldParts.d.ts +2 -1
  46. package/dist/components/DateFieldParts.js +7 -0
  47. package/dist/components/DatePicker.d.ts +9 -2
  48. package/dist/components/DatePicker.js +67 -28
  49. package/dist/components/DateRangePicker.d.ts +12 -2
  50. package/dist/components/DateRangePicker.js +13 -12
  51. package/dist/components/DetailPage.d.ts +7 -1
  52. package/dist/components/DetailPage.js +2 -1
  53. package/dist/components/Dialogs.d.ts +71 -10
  54. package/dist/components/Dialogs.js +130 -30
  55. package/dist/components/DiffViewer.d.ts +23 -3
  56. package/dist/components/DiffViewer.js +26 -12
  57. package/dist/components/DiscardPrompt.js +16 -0
  58. package/dist/components/DisplayPreferences.d.ts +83 -0
  59. package/dist/components/DisplayPreferences.js +185 -0
  60. package/dist/components/EditorialHome.d.ts +23 -3
  61. package/dist/components/EditorialHome.js +16 -11
  62. package/dist/components/EntityPicker.d.ts +20 -3
  63. package/dist/components/EntityPicker.js +32 -13
  64. package/dist/components/FilterEditor.d.ts +18 -4
  65. package/dist/components/FilterEditor.js +141 -19
  66. package/dist/components/FocusOnMount.d.ts +282 -0
  67. package/dist/components/FocusOnMount.js +12 -0
  68. package/dist/components/InfoTip.js +11 -12
  69. package/dist/components/InlineEdit.d.ts +87 -20
  70. package/dist/components/InlineEdit.js +197 -54
  71. package/dist/components/Input.d.ts +12 -2
  72. package/dist/components/Input.js +5 -3
  73. package/dist/components/Kanban.d.ts +14 -3
  74. package/dist/components/Kanban.js +9 -4
  75. package/dist/components/Kbd.d.ts +6 -1
  76. package/dist/components/Kbd.js +6 -6
  77. package/dist/components/Lightbox.d.ts +41 -5
  78. package/dist/components/Lightbox.js +95 -9
  79. package/dist/components/MatchReview.d.ts +40 -1
  80. package/dist/components/MatchReview.js +130 -4
  81. package/dist/components/MetricInput.js +3 -2
  82. package/dist/components/Modal.d.ts +2 -1
  83. package/dist/components/Modal.js +13 -4
  84. package/dist/components/MotionList.d.ts +303 -0
  85. package/dist/components/MotionList.js +175 -0
  86. package/dist/components/NavFavourites.d.ts +5 -0
  87. package/dist/components/NavFavourites.js +7 -7
  88. package/dist/components/OtpInput.d.ts +33 -0
  89. package/dist/components/OtpInput.js +123 -0
  90. package/dist/components/PageHeader.d.ts +7 -1
  91. package/dist/components/PageHeader.js +2 -2
  92. package/dist/components/Pagination.js +6 -5
  93. package/dist/components/PasswordInput.d.ts +34 -0
  94. package/dist/components/PasswordInput.js +101 -0
  95. package/dist/components/Peek.js +3 -3
  96. package/dist/components/Popover.js +11 -0
  97. package/dist/components/PrintLayout.d.ts +63 -0
  98. package/dist/components/PrintLayout.js +114 -0
  99. package/dist/components/QrCode.d.ts +47 -0
  100. package/dist/components/QrCode.js +55 -0
  101. package/dist/components/QrScanner.d.ts +95 -0
  102. package/dist/components/QrScanner.js +266 -0
  103. package/dist/components/RelationshipGraph.d.ts +32 -1
  104. package/dist/components/RelationshipGraph.js +22 -6
  105. package/dist/components/RelationshipGraphLayered.d.ts +1 -1
  106. package/dist/components/RelationshipGraphLayered.js +268 -118
  107. package/dist/components/RelationshipGraphList.js +33 -6
  108. package/dist/components/RuleBuilder.js +39 -7
  109. package/dist/components/SchedulingAgenda.d.ts +3 -1
  110. package/dist/components/SchedulingCalendar.d.ts +3 -1
  111. package/dist/components/SchedulingCalendar.js +43 -4
  112. package/dist/components/SchedulingResourceDay.d.ts +57 -0
  113. package/dist/components/SchedulingResourceDay.js +287 -0
  114. package/dist/components/SchedulingTimeGrid.d.ts +3 -1
  115. package/dist/components/SchedulingTimeline.d.ts +3 -1
  116. package/dist/components/SearchSuggest.d.ts +23 -3
  117. package/dist/components/SearchSuggest.js +56 -18
  118. package/dist/components/Segmented.d.ts +39 -4
  119. package/dist/components/Segmented.js +39 -5
  120. package/dist/components/Select.d.ts +3 -2
  121. package/dist/components/Select.js +7 -1
  122. package/dist/components/ShortcutHint.d.ts +11 -10
  123. package/dist/components/ShortcutHint.js +44 -38
  124. package/dist/components/Sidebar.d.ts +36 -4
  125. package/dist/components/Sidebar.js +37 -12
  126. package/dist/components/SortableList.d.ts +45 -0
  127. package/dist/components/SortableList.js +147 -0
  128. package/dist/components/Stat.d.ts +28 -3
  129. package/dist/components/Stat.js +13 -3
  130. package/dist/components/States.d.ts +33 -1
  131. package/dist/components/States.js +43 -1
  132. package/dist/components/StatusPill.d.ts +14 -3
  133. package/dist/components/StatusPill.js +11 -3
  134. package/dist/components/Steps.js +2 -1
  135. package/dist/components/Table.d.ts +9 -2
  136. package/dist/components/Table.js +4 -2
  137. package/dist/components/TableControls.js +18 -58
  138. package/dist/components/TableOverflowProbe.d.ts +12 -0
  139. package/dist/components/TableOverflowProbe.js +27 -0
  140. package/dist/components/Tabs.d.ts +2 -1
  141. package/dist/components/Tabs.js +10 -2
  142. package/dist/components/TagInput.d.ts +67 -0
  143. package/dist/components/TagInput.js +342 -0
  144. package/dist/components/Textarea.d.ts +5 -0
  145. package/dist/components/Textarea.js +2 -2
  146. package/dist/components/TimePicker.d.ts +80 -0
  147. package/dist/components/TimePicker.js +347 -0
  148. package/dist/components/Toast.d.ts +1 -1
  149. package/dist/components/Toast.js +109 -4
  150. package/dist/components/Tooltip.d.ts +8 -4
  151. package/dist/components/Tooltip.js +86 -28
  152. package/dist/components/Tree.d.ts +8 -0
  153. package/dist/components/Tree.js +11 -5
  154. package/dist/display-preferences-model.d.ts +53 -0
  155. package/dist/display-preferences-model.js +64 -0
  156. package/dist/emoji.cjs +143 -49
  157. package/dist/filter-model.d.ts +59 -3
  158. package/dist/filter-model.js +67 -2
  159. package/dist/hooks/useAnchoredPosition.js +14 -2
  160. package/dist/hooks/useChangeHighlight.d.ts +33 -0
  161. package/dist/hooks/useChangeHighlight.js +44 -0
  162. package/dist/hooks/useDeferredReorder.d.ts +32 -0
  163. package/dist/hooks/useDeferredReorder.js +47 -0
  164. package/dist/hooks/useDialog.d.ts +5 -0
  165. package/dist/hooks/useDialog.js +17 -3
  166. package/dist/hooks/useKeyboardGrab.d.ts +58 -0
  167. package/dist/hooks/useKeyboardGrab.js +118 -0
  168. package/dist/hooks/useOptimisticValue.d.ts +51 -0
  169. package/dist/hooks/useOptimisticValue.js +61 -0
  170. package/dist/hooks/useReducedMotion.d.ts +4 -1
  171. package/dist/hooks/useReducedMotion.js +7 -1
  172. package/dist/hooks/useResolvedFilterLabels.d.ts +15 -0
  173. package/dist/hooks/useResolvedFilterLabels.js +34 -0
  174. package/dist/hooks/useSlidingIndicator.d.ts +18 -0
  175. package/dist/hooks/useSlidingIndicator.js +80 -0
  176. package/dist/hooks/useVirtualRows.d.ts +21 -2
  177. package/dist/hooks/useVirtualRows.js +30 -3
  178. package/dist/icons/Icon.d.ts +1 -1
  179. package/dist/index.cjs +19687 -13423
  180. package/dist/index.d.cts +3419 -651
  181. package/dist/index.d.ts +48 -18
  182. package/dist/index.js +153 -9
  183. package/dist/labels-context.d.ts +93 -3
  184. package/dist/motion.d.ts +11 -0
  185. package/dist/motion.js +35 -0
  186. package/dist/overlay-stack.d.ts +6 -0
  187. package/dist/overlay-stack.js +13 -0
  188. package/dist/qr-model.d.ts +65 -0
  189. package/dist/qr-model.js +323 -0
  190. package/dist/relationship-graph-model.d.ts +92 -3
  191. package/dist/relationship-graph-model.js +134 -15
  192. package/dist/reorder.d.ts +30 -0
  193. package/dist/reorder.js +74 -0
  194. package/dist/rich-text.cjs +46 -4
  195. package/dist/scheduling-resource-model.d.ts +76 -0
  196. package/dist/scheduling-resource-model.js +74 -0
  197. package/dist/search-suggest-model.js +3 -1
  198. package/dist/shell-context.d.ts +11 -0
  199. package/dist/shell-context.js +7 -0
  200. package/dist/time-field-model.d.ts +46 -0
  201. package/dist/time-field-model.js +152 -0
  202. package/dist/toast-store.d.ts +22 -3
  203. package/dist/toast-store.js +26 -9
  204. package/package.json +2 -1
@@ -1,63 +1,121 @@
1
1
  "use client";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import { cloneElement, isValidElement, useEffect, useId, useRef, useState } from "react";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { cloneElement, isValidElement, useEffect, useId, useLayoutEffect, useRef, useState } from "react";
4
4
  import { cx } from "../cx.js";
5
5
  import { useAnchoredPosition } from "../hooks/useAnchoredPosition.js";
6
- import { KbdCombo, ariaKeyShortcuts, isKeyShortcut, useKbdPlatform } from "./Kbd.js";
6
+ import { KbdCombo, isKeyShortcut, spokenKeys, useKbdPlatform } from "./Kbd.js";
7
+ import { markKeyOpened, tokenMs, watchInputModality } from "../motion.js";
8
+ const group = { open: 0, lastClosed: -Infinity, current: null };
9
+ const useIsomorphicLayoutEffect = typeof document !== "undefined" ? useLayoutEffect : useEffect;
7
10
  function Tooltip({ label, content, placement = "top", shortcut, className, children, ...props }) {
8
11
  const triggerRef = useRef(null);
9
12
  const bubbleRef = useRef(null);
10
13
  const closeTimer = useRef(null);
14
+ const openTimer = useRef(null);
15
+ const shown = useRef(false);
11
16
  const [open, setOpen] = useState(false);
12
17
  const id = useId();
13
18
  const platform = useKbdPlatform();
14
19
  const childShortcut = isValidElement(children) ? children.props.shortcut : void 0;
15
20
  const own = shortcut ?? (isKeyShortcut(childShortcut) ? childShortcut : void 0);
16
21
  const keys = own && own.length > 0 ? own : null;
17
- const keyshortcuts = keys ? ariaKeyShortcuts(keys, platform) : void 0;
18
22
  useAnchoredPosition(triggerRef, bubbleRef, { open, placement, offset: 6 });
23
+ useEffect(() => {
24
+ watchInputModality();
25
+ }, []);
19
26
  const cancelClose = () => {
20
27
  if (closeTimer.current != null) {
21
28
  clearTimeout(closeTimer.current);
22
29
  closeTimer.current = null;
23
30
  }
24
31
  };
25
- const show = () => {
26
- cancelClose();
32
+ const cancelOpen = () => {
33
+ if (openTimer.current != null) {
34
+ clearTimeout(openTimer.current);
35
+ openTimer.current = null;
36
+ }
37
+ };
38
+ const reveal = (instant) => {
39
+ cancelOpen();
40
+ if (group.current && group.current !== self) group.current.current(true);
41
+ group.current = self;
27
42
  const b = bubbleRef.current;
28
43
  if (b && !b.matches(":popover-open")) {
44
+ b.toggleAttribute("data-uix-instant", instant);
45
+ markKeyOpened(b);
29
46
  try {
30
47
  b.showPopover();
31
48
  } catch {
32
49
  }
33
50
  }
51
+ if (!shown.current) {
52
+ shown.current = true;
53
+ group.open += 1;
54
+ }
34
55
  setOpen(true);
35
56
  };
36
- const hide = () => {
57
+ const show = (via) => {
58
+ cancelClose();
59
+ if (shown.current) return;
60
+ const warm = group.open > 0 || performance.now() - group.lastClosed < tokenMs("--uix-delay-tooltip-skip", 300);
61
+ if (via === "focus" || warm) {
62
+ reveal(via === "pointer");
63
+ return;
64
+ }
65
+ if (openTimer.current == null) openTimer.current = window.setTimeout(() => reveal(false), tokenMs("--uix-delay-tooltip", 400));
66
+ };
67
+ const hide = (instant = false) => {
37
68
  cancelClose();
69
+ cancelOpen();
38
70
  const b = bubbleRef.current;
39
71
  if (b && b.matches(":popover-open")) {
72
+ b.toggleAttribute("data-uix-instant", instant);
40
73
  try {
41
74
  b.hidePopover();
42
75
  } catch {
43
76
  }
44
77
  }
78
+ if (shown.current) {
79
+ shown.current = false;
80
+ group.open -= 1;
81
+ group.lastClosed = performance.now();
82
+ }
83
+ if (group.current === self) group.current = null;
45
84
  setOpen(false);
46
85
  };
86
+ const self = useRef(hide);
87
+ self.current = hide;
47
88
  const scheduleHide = () => {
48
89
  cancelClose();
49
- closeTimer.current = window.setTimeout(hide, 100);
90
+ closeTimer.current = window.setTimeout(() => {
91
+ closeTimer.current = null;
92
+ try {
93
+ if (triggerRef.current?.matches(":hover")) return;
94
+ } catch {
95
+ }
96
+ hide();
97
+ }, 100);
50
98
  };
51
- useEffect(() => {
52
- if (!open) return;
99
+ useIsomorphicLayoutEffect(() => {
100
+ if (!open) return void 0;
53
101
  const onKey = (e) => {
54
- if (e.key === "Escape") hide();
102
+ if (e.key !== "Escape") return;
103
+ e.preventDefault();
104
+ e.stopPropagation();
105
+ hide();
55
106
  };
56
- document.addEventListener("keydown", onKey);
57
- return () => document.removeEventListener("keydown", onKey);
107
+ document.addEventListener("keydown", onKey, true);
108
+ return () => document.removeEventListener("keydown", onKey, true);
58
109
  }, [open]);
59
110
  useEffect(() => () => {
60
111
  if (closeTimer.current != null) clearTimeout(closeTimer.current);
112
+ if (openTimer.current != null) clearTimeout(openTimer.current);
113
+ if (shown.current) {
114
+ shown.current = false;
115
+ group.open -= 1;
116
+ group.lastClosed = performance.now();
117
+ }
118
+ if (group.current === self) group.current = null;
61
119
  const b = bubbleRef.current;
62
120
  if (b && b.matches(":popover-open")) {
63
121
  try {
@@ -67,30 +125,27 @@ function Tooltip({ label, content, placement = "top", shortcut, className, child
67
125
  }
68
126
  }, []);
69
127
  const bubbleAttr = { popover: "manual" };
128
+ const text = content ?? label;
129
+ const description = keys ? [text != null ? `${id}-text` : null, `${id}-keys`].filter(Boolean).join(" ") : id;
70
130
  const single = isValidElement(children);
71
131
  const child = single ? cloneElement(children, {
72
- "aria-describedby": [children.props["aria-describedby"], id].filter(Boolean).join(" "),
73
- ...keyshortcuts ? { "aria-keyshortcuts": keyshortcuts } : {}
132
+ "aria-describedby": [children.props["aria-describedby"], description].filter(Boolean).join(" ")
74
133
  }) : children;
75
134
  return /* @__PURE__ */ jsxs(
76
135
  "span",
77
136
  {
78
137
  ref: triggerRef,
79
138
  className: cx("uix-tooltip", className),
80
- "aria-describedby": single ? void 0 : id,
81
- "aria-keyshortcuts": single ? void 0 : keyshortcuts,
139
+ "aria-describedby": single ? void 0 : description,
82
140
  tabIndex: single ? void 0 : 0,
83
- onMouseEnter: show,
141
+ onMouseEnter: () => show("pointer"),
84
142
  onMouseLeave: scheduleHide,
85
- onFocus: show,
86
- onBlur: hide,
87
- onKeyDown: (e) => {
88
- if (e.key === "Escape") hide();
89
- },
143
+ onFocus: () => show("focus"),
144
+ onBlur: () => hide(),
90
145
  ...props,
91
146
  children: [
92
147
  child,
93
- /* @__PURE__ */ jsxs(
148
+ /* @__PURE__ */ jsx(
94
149
  "span",
95
150
  {
96
151
  ref: bubbleRef,
@@ -100,10 +155,13 @@ function Tooltip({ label, content, placement = "top", shortcut, className, child
100
155
  onMouseEnter: cancelClose,
101
156
  onMouseLeave: scheduleHide,
102
157
  ...bubbleAttr,
103
- children: [
104
- content ?? label,
105
- keys && /* @__PURE__ */ jsx("span", { className: "uix-tooltip__shortcut", children: /* @__PURE__ */ jsx(KbdCombo, { keys: [...keys], platform }) })
106
- ]
158
+ children: keys ? /* @__PURE__ */ jsxs(Fragment, { children: [
159
+ text != null && /* @__PURE__ */ jsx("span", { id: `${id}-text`, children: text }),
160
+ /* @__PURE__ */ jsxs("span", { className: "uix-tooltip__shortcut", children: [
161
+ /* @__PURE__ */ jsx("span", { id: `${id}-keys`, className: "uix-visually-hidden", children: spokenKeys(keys, platform) }),
162
+ /* @__PURE__ */ jsx(KbdCombo, { keys: [...keys], platform, "aria-hidden": "true" })
163
+ ] })
164
+ ] }) : text
107
165
  }
108
166
  )
109
167
  ]
@@ -6,6 +6,12 @@ interface TreeNodeData {
6
6
  label: ReactNode;
7
7
  /** Plain-text label for keyboard typeahead when `label` is not a string (UIX-A11Y-2). */
8
8
  typeaheadLabel?: string;
9
+ /**
10
+ * The row's accessible name when `label` is rich (an avatar, a name and a meta line) and only
11
+ * part of it should be spoken, e.g. the person's name (HAR-1828). By default a row is named by
12
+ * its own `label`, never by its children.
13
+ */
14
+ ariaLabel?: string;
9
15
  icon?: ReactNode;
10
16
  children?: TreeNodeData[];
11
17
  /**
@@ -39,6 +45,8 @@ interface TreeNodeProps {
39
45
  rowToggles?: boolean;
40
46
  /** Ids of nodes whose children are loading (`aria-busy`). */
41
47
  busy?: ReadonlySet<string>;
48
+ /** Scopes the ids that name each row by its own label (HAR-1828). Set by `Tree`. */
49
+ treeId?: string;
42
50
  }
43
51
  interface TreeProps extends Omit<HTMLAttributes<HTMLUListElement>, 'onSelect' | 'onChange'> {
44
52
  nodes: TreeNodeData[];
@@ -15,13 +15,16 @@ const LOADING = "::uix-loading";
15
15
  const FAILED = "::uix-error";
16
16
  const syntheticOf = (id) => id.endsWith(LOADING) ? { parent: id.slice(0, -LOADING.length), kind: "loading" } : id.endsWith(FAILED) ? { parent: id.slice(0, -FAILED.length), kind: "error" } : null;
17
17
  const Ring = () => /* @__PURE__ */ jsx("span", { className: "uix-spinner uix-spinner--sm", "aria-hidden": "true" });
18
- function TreeNode({ node, expanded, selected, selectable, tabbableId, onToggle, onSelect, onFocusNode, level = 1, rowToggles = true, busy }) {
18
+ const labelId = (treeId, nodeId) => `${treeId}-label-${encodeURIComponent(nodeId)}`;
19
+ const rowName = (treeId, node) => node.ariaLabel ? { "aria-label": node.ariaLabel } : { "aria-labelledby": labelId(treeId, node.id) };
20
+ function TreeNode({ node, expanded, selected, selectable, tabbableId, onToggle, onSelect, onFocusNode, level = 1, rowToggles = true, busy, treeId = "uix-tree" }) {
19
21
  const hasChildren = Array.isArray(node.children) && node.children.length > 0;
20
22
  const isExpanded = expanded.has(node.id);
21
23
  return /* @__PURE__ */ jsxs(
22
24
  "li",
23
25
  {
24
26
  role: "treeitem",
27
+ ...rowName(treeId, node),
25
28
  "aria-level": level,
26
29
  "aria-expanded": hasChildren ? isExpanded : void 0,
27
30
  "aria-selected": selectable && !syntheticOf(node.id) ? selected === node.id : void 0,
@@ -61,7 +64,7 @@ function TreeNode({ node, expanded, selected, selectable, tabbableId, onToggle,
61
64
  )
62
65
  ) : /* @__PURE__ */ jsx("span", { className: "uix-tree__toggle" }),
63
66
  node.icon && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: node.icon }),
64
- /* @__PURE__ */ jsx("span", { className: "uix-tree__label", children: node.label })
67
+ /* @__PURE__ */ jsx("span", { id: labelId(treeId, node.id), className: "uix-tree__label", children: node.label })
65
68
  ] }),
66
69
  hasChildren && isExpanded && /* @__PURE__ */ jsx("ul", { role: "group", className: "uix-tree__group", children: node.children.map((child) => /* @__PURE__ */ jsx(
67
70
  TreeNode,
@@ -76,7 +79,8 @@ function TreeNode({ node, expanded, selected, selectable, tabbableId, onToggle,
76
79
  onFocusNode,
77
80
  level: level + 1,
78
81
  rowToggles,
79
- busy
82
+ busy,
83
+ treeId
80
84
  },
81
85
  child.id
82
86
  )) })
@@ -317,7 +321,8 @@ function Tree({
317
321
  onFocusNode: setFocusedId,
318
322
  level: 1,
319
323
  rowToggles,
320
- busy: loading
324
+ busy: loading,
325
+ treeId
321
326
  },
322
327
  node.id
323
328
  )) });
@@ -418,6 +423,7 @@ function VirtualTreeView({
418
423
  "li",
419
424
  {
420
425
  role: "treeitem",
426
+ ...rowName(treeId, f.node),
421
427
  "aria-level": f.level,
422
428
  "aria-setsize": f.setsize,
423
429
  "aria-posinset": f.posinset,
@@ -458,7 +464,7 @@ function VirtualTreeView({
458
464
  )
459
465
  ) : /* @__PURE__ */ jsx("span", { className: "uix-tree__toggle" }),
460
466
  f.node.icon && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: f.node.icon }),
461
- /* @__PURE__ */ jsx("span", { className: "uix-tree__label", children: f.node.label })
467
+ /* @__PURE__ */ jsx("span", { id: labelId(treeId, f.node.id), className: "uix-tree__label", children: f.node.label })
462
468
  ] })
463
469
  },
464
470
  f.node.id
@@ -0,0 +1,53 @@
1
+ type ThemePreference = 'light' | 'dark' | 'system';
2
+ type ContrastPreference = 'standard' | 'more' | 'system';
3
+ type TextScalePreference = 'sm' | 'md' | 'lg' | 'xl';
4
+ type MotionPreference = 'system' | 'reduce';
5
+ type DensityPreference = 'compact' | 'standard' | 'comfortable';
6
+ interface DisplayPreferenceValues {
7
+ theme: ThemePreference;
8
+ contrast: ContrastPreference;
9
+ textScale: TextScalePreference;
10
+ motion: MotionPreference;
11
+ density: DensityPreference;
12
+ }
13
+ /** What the system says, for the `system` choices. */
14
+ interface SystemDisplayPreferences {
15
+ dark: boolean;
16
+ moreContrast: boolean;
17
+ }
18
+ /** The attributes written on <html>; `undefined` means the attribute is removed. */
19
+ interface DisplayAttributes {
20
+ 'data-theme': 'light' | 'dark';
21
+ 'data-contrast'?: 'more';
22
+ 'data-text-scale'?: 'sm' | 'lg' | 'xl';
23
+ 'data-motion'?: 'reduce';
24
+ 'data-density'?: 'compact' | 'comfortable';
25
+ }
26
+ declare const DEFAULT_DISPLAY_PREFERENCES: DisplayPreferenceValues;
27
+ /** The default `localStorage` key. */
28
+ declare const DISPLAY_PREFERENCES_STORAGE_KEY = "uix-display-preferences";
29
+ declare const DISPLAY_PREFERENCE_OPTIONS: {
30
+ readonly theme: readonly ["light", "dark", "system"];
31
+ readonly contrast: readonly ["standard", "more", "system"];
32
+ readonly textScale: readonly ["sm", "md", "lg", "xl"];
33
+ readonly motion: readonly ["system", "reduce"];
34
+ readonly density: readonly ["compact", "standard", "comfortable"];
35
+ };
36
+ /** Read stored preferences; anything missing or unknown falls back to `defaults`. */
37
+ declare function parseDisplayPreferences(raw: string | null | undefined, defaults?: DisplayPreferenceValues): DisplayPreferenceValues;
38
+ /** The <html> attributes for a set of preferences, resolving `system` against the system. */
39
+ declare function resolveDisplayAttributes(prefs: DisplayPreferenceValues, system: SystemDisplayPreferences): DisplayAttributes;
40
+ /** Write (or remove) the attributes on an element, normally `document.documentElement`. */
41
+ declare function applyDisplayAttributes(root: Element, attributes: DisplayAttributes): void;
42
+ /** The system's answers from `matchMedia`; all false where there is none (SSR, tests). */
43
+ declare function readSystemDisplayPreferences(): SystemDisplayPreferences;
44
+ /**
45
+ * An inline script for the document head that applies the stored preferences before the first
46
+ * paint, so a dark or large-text page never flashes light or small (HAR-1372). Self-contained ES5;
47
+ * it never throws. Put it in a `<script>` before the stylesheets:
48
+ * <script dangerouslySetInnerHTML={{ __html: displayPreferencesScript() }} />
49
+ * It mirrors parseDisplayPreferences + resolveDisplayAttributes (tested to agree).
50
+ */
51
+ declare function displayPreferencesScript(storageKey?: string, defaults?: DisplayPreferenceValues): string;
52
+
53
+ export { type ContrastPreference, DEFAULT_DISPLAY_PREFERENCES, DISPLAY_PREFERENCES_STORAGE_KEY, DISPLAY_PREFERENCE_OPTIONS, type DensityPreference, type DisplayAttributes, type DisplayPreferenceValues, type MotionPreference, type SystemDisplayPreferences, type TextScalePreference, type ThemePreference, applyDisplayAttributes, displayPreferencesScript, parseDisplayPreferences, readSystemDisplayPreferences, resolveDisplayAttributes };
@@ -0,0 +1,64 @@
1
+ const DEFAULT_DISPLAY_PREFERENCES = {
2
+ theme: "system",
3
+ contrast: "system",
4
+ textScale: "md",
5
+ motion: "system",
6
+ density: "standard"
7
+ };
8
+ const DISPLAY_PREFERENCES_STORAGE_KEY = "uix-display-preferences";
9
+ const DISPLAY_PREFERENCE_OPTIONS = {
10
+ theme: ["light", "dark", "system"],
11
+ contrast: ["standard", "more", "system"],
12
+ textScale: ["sm", "md", "lg", "xl"],
13
+ motion: ["system", "reduce"],
14
+ density: ["compact", "standard", "comfortable"]
15
+ };
16
+ function parseDisplayPreferences(raw, defaults = DEFAULT_DISPLAY_PREFERENCES) {
17
+ let stored = {};
18
+ try {
19
+ stored = raw ? JSON.parse(raw) ?? {} : {};
20
+ } catch {
21
+ stored = {};
22
+ }
23
+ if (typeof stored !== "object") stored = {};
24
+ const pick = (key) => {
25
+ const value = stored[key];
26
+ return DISPLAY_PREFERENCE_OPTIONS[key].includes(value) ? value : defaults[key];
27
+ };
28
+ return { theme: pick("theme"), contrast: pick("contrast"), textScale: pick("textScale"), motion: pick("motion"), density: pick("density") };
29
+ }
30
+ function resolveDisplayAttributes(prefs, system) {
31
+ const theme = prefs.theme === "system" ? system.dark ? "dark" : "light" : prefs.theme;
32
+ const more = prefs.contrast === "more" || prefs.contrast === "system" && system.moreContrast;
33
+ return {
34
+ "data-theme": theme,
35
+ "data-contrast": more ? "more" : void 0,
36
+ "data-text-scale": prefs.textScale === "md" ? void 0 : prefs.textScale,
37
+ "data-motion": prefs.motion === "reduce" ? "reduce" : void 0,
38
+ "data-density": prefs.density === "standard" ? void 0 : prefs.density
39
+ };
40
+ }
41
+ function applyDisplayAttributes(root, attributes) {
42
+ for (const name of ["data-theme", "data-contrast", "data-text-scale", "data-motion", "data-density"]) {
43
+ const value = attributes[name];
44
+ if (value == null) root.removeAttribute(name);
45
+ else if (root.getAttribute(name) !== value) root.setAttribute(name, value);
46
+ }
47
+ }
48
+ function readSystemDisplayPreferences() {
49
+ const mm = (query) => typeof matchMedia === "function" && matchMedia(query).matches;
50
+ return { dark: mm("(prefers-color-scheme: dark)"), moreContrast: mm("(prefers-contrast: more)") };
51
+ }
52
+ function displayPreferencesScript(storageKey = DISPLAY_PREFERENCES_STORAGE_KEY, defaults = DEFAULT_DISPLAY_PREFERENCES) {
53
+ return `(function(){try{var d=document.documentElement,p={};try{p=JSON.parse(localStorage.getItem(${JSON.stringify(storageKey)})||'{}')||{}}catch(e){}if(typeof p!=='object')p={};var D=${JSON.stringify(defaults)},O=${JSON.stringify(DISPLAY_PREFERENCE_OPTIONS)};for(var k in O)if(O[k].indexOf(p[k])<0)p[k]=D[k];var m=function(q){return !!(window.matchMedia&&window.matchMedia(q).matches)};var s=function(n,v){if(v)d.setAttribute(n,v);else d.removeAttribute(n)};s('data-theme',p.theme==='light'||p.theme==='dark'?p.theme:(m('(prefers-color-scheme: dark)')?'dark':'light'));s('data-contrast',p.contrast==='more'||(p.contrast!=='standard'&&m('(prefers-contrast: more)'))?'more':'');s('data-text-scale',p.textScale==='sm'||p.textScale==='lg'||p.textScale==='xl'?p.textScale:'');s('data-motion',p.motion==='reduce'?'reduce':'');s('data-density',p.density==='compact'||p.density==='comfortable'?p.density:'')}catch(e){}})();`;
54
+ }
55
+ export {
56
+ DEFAULT_DISPLAY_PREFERENCES,
57
+ DISPLAY_PREFERENCES_STORAGE_KEY,
58
+ DISPLAY_PREFERENCE_OPTIONS,
59
+ applyDisplayAttributes,
60
+ displayPreferencesScript,
61
+ parseDisplayPreferences,
62
+ readSystemDisplayPreferences,
63
+ resolveDisplayAttributes
64
+ };