efficient-shell 4.134.0 → 4.137.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 (87) hide show
  1. package/README.md +81 -7
  2. package/dist/{Browser-O3QZGUF2.js → Browser-ZNX4WFUH.js} +11 -11
  3. package/dist/{Browser-O3QZGUF2.js.map → Browser-ZNX4WFUH.js.map} +1 -1
  4. package/dist/{Calculator-L6N5X3KU.js → Calculator-6FGNKOXU.js} +10 -10
  5. package/dist/{Calculator-L6N5X3KU.js.map → Calculator-6FGNKOXU.js.map} +1 -1
  6. package/dist/ConfirmDialog-NPQMIGUR.js +4 -0
  7. package/dist/{ConfirmDialog-LYSSZSUD.js.map → ConfirmDialog-NPQMIGUR.js.map} +1 -1
  8. package/dist/{CurrencyConverter-64MKXB3D.js → CurrencyConverter-FF7EXRYL.js} +10 -10
  9. package/dist/{CurrencyConverter-64MKXB3D.js.map → CurrencyConverter-FF7EXRYL.js.map} +1 -1
  10. package/dist/{Documents-5WXXYCLI.js → Documents-H3R7XSBH.js} +12 -12
  11. package/dist/{Documents-5WXXYCLI.js.map → Documents-H3R7XSBH.js.map} +1 -1
  12. package/dist/{Files-AUURUUDN.js → Files-ZHJIAUC2.js} +15 -15
  13. package/dist/{Files-AUURUUDN.js.map → Files-ZHJIAUC2.js.map} +1 -1
  14. package/dist/{Notepad-GPXJVPB7.js → Notepad-VE7ISWRQ.js} +13 -13
  15. package/dist/{Notepad-GPXJVPB7.js.map → Notepad-VE7ISWRQ.js.map} +1 -1
  16. package/dist/PdfViewer-SQBFYAGW.js +5 -0
  17. package/dist/{PdfViewer-HKO6P4SR.js.map → PdfViewer-SQBFYAGW.js.map} +1 -1
  18. package/dist/{PomodoroTimer-4TQBWLP2.js → PomodoroTimer-IR3WREED.js} +12 -12
  19. package/dist/{PomodoroTimer-4TQBWLP2.js.map → PomodoroTimer-IR3WREED.js.map} +1 -1
  20. package/dist/{Preview-FOZYPKM2.js → Preview-DAQGRNRM.js} +14 -14
  21. package/dist/{Preview-FOZYPKM2.js.map → Preview-DAQGRNRM.js.map} +1 -1
  22. package/dist/{Sidebar-BPU7RCZP.js → Sidebar-YW6H4NDJ.js} +3 -3
  23. package/dist/{Sidebar-BPU7RCZP.js.map → Sidebar-YW6H4NDJ.js.map} +1 -1
  24. package/dist/{Spreadsheet-3C66BBBF.js → Spreadsheet-HOCPHJOC.js} +12 -12
  25. package/dist/{Spreadsheet-3C66BBBF.js.map → Spreadsheet-HOCPHJOC.js.map} +1 -1
  26. package/dist/{Stock-IF4IHYLU.js → Stock-LVRQPURG.js} +10 -10
  27. package/dist/{Stock-IF4IHYLU.js.map → Stock-LVRQPURG.js.map} +1 -1
  28. package/dist/{Weather-725PFR7T.js → Weather-LZQGVDJL.js} +10 -10
  29. package/dist/{Weather-725PFR7T.js.map → Weather-LZQGVDJL.js.map} +1 -1
  30. package/dist/{WorldClock-UU4NZIQ7.js → WorldClock-XPD7WOZT.js} +10 -10
  31. package/dist/{WorldClock-UU4NZIQ7.js.map → WorldClock-XPD7WOZT.js.map} +1 -1
  32. package/dist/apps/index.js +23 -23
  33. package/dist/brand.css +1 -1
  34. package/dist/{chunk-GIGV2ZRW.js → chunk-5RPTS3BT.js} +3 -3
  35. package/dist/{chunk-GIGV2ZRW.js.map → chunk-5RPTS3BT.js.map} +1 -1
  36. package/dist/{chunk-D276EMXS.js → chunk-6XJEJWNJ.js} +7 -3
  37. package/dist/chunk-6XJEJWNJ.js.map +1 -0
  38. package/dist/{chunk-IULP5BCD.js → chunk-COWYSHG2.js} +4 -4
  39. package/dist/{chunk-IULP5BCD.js.map → chunk-COWYSHG2.js.map} +1 -1
  40. package/dist/{chunk-R4OQIQYX.js → chunk-E7TB6WD2.js} +4 -4
  41. package/dist/{chunk-R4OQIQYX.js.map → chunk-E7TB6WD2.js.map} +1 -1
  42. package/dist/{chunk-X4Q6G253.js → chunk-FIHOGVUP.js} +3 -3
  43. package/dist/{chunk-X4Q6G253.js.map → chunk-FIHOGVUP.js.map} +1 -1
  44. package/dist/{chunk-2TPTHAKI.js → chunk-HUBJAUGG.js} +3 -3
  45. package/dist/{chunk-2TPTHAKI.js.map → chunk-HUBJAUGG.js.map} +1 -1
  46. package/dist/{chunk-W622KQTD.js → chunk-I2TAAJHS.js} +3 -3
  47. package/dist/{chunk-W622KQTD.js.map → chunk-I2TAAJHS.js.map} +1 -1
  48. package/dist/{chunk-Q3LT745N.js → chunk-ICTRCKUE.js} +7 -7
  49. package/dist/{chunk-Q3LT745N.js.map → chunk-ICTRCKUE.js.map} +1 -1
  50. package/dist/{chunk-QRL64J5F.js → chunk-JOPU6WPY.js} +7 -6
  51. package/dist/chunk-JOPU6WPY.js.map +1 -0
  52. package/dist/{chunk-PIGDNN5F.js → chunk-PVPPAWVM.js} +3 -3
  53. package/dist/{chunk-PIGDNN5F.js.map → chunk-PVPPAWVM.js.map} +1 -1
  54. package/dist/{chunk-ET6ID4LP.js → chunk-R7QGMK6N.js} +3 -3
  55. package/dist/{chunk-ET6ID4LP.js.map → chunk-R7QGMK6N.js.map} +1 -1
  56. package/dist/{chunk-4P44JXDS.js → chunk-UTYKLGGT.js} +3 -3
  57. package/dist/{chunk-4P44JXDS.js.map → chunk-UTYKLGGT.js.map} +1 -1
  58. package/dist/{chunk-T4VQHMG4.js → chunk-VNJJCH5A.js} +3 -3
  59. package/dist/{chunk-T4VQHMG4.js.map → chunk-VNJJCH5A.js.map} +1 -1
  60. package/dist/{chunk-QSKCQUZE.js → chunk-XJHZWSKV.js} +3 -3
  61. package/dist/{chunk-QSKCQUZE.js.map → chunk-XJHZWSKV.js.map} +1 -1
  62. package/dist/{chunk-SHQM5CK3.js → chunk-Y3GYJ7YR.js} +4 -4
  63. package/dist/{chunk-SHQM5CK3.js.map → chunk-Y3GYJ7YR.js.map} +1 -1
  64. package/dist/{chunk-OLJDJYSU.js → chunk-YA4EE7ST.js} +574 -145
  65. package/dist/chunk-YA4EE7ST.js.map +1 -0
  66. package/dist/{chunk-QAGQRNKI.js → chunk-YDHXWCCJ.js} +3 -3
  67. package/dist/{chunk-QAGQRNKI.js.map → chunk-YDHXWCCJ.js.map} +1 -1
  68. package/dist/{chunk-72CQWN7O.js → chunk-YE6GUDGP.js} +3 -2
  69. package/dist/chunk-YE6GUDGP.js.map +1 -0
  70. package/dist/chunk-ZS7PMGUW.js +7 -0
  71. package/dist/{chunk-Q2MJVSJT.js.map → chunk-ZS7PMGUW.js.map} +1 -1
  72. package/dist/file-intake/index.js +2 -2
  73. package/dist/{index-DZ7E7bCl.d.ts → index-DVI9DMSu.d.ts} +189 -18
  74. package/dist/index.d.ts +2 -2
  75. package/dist/index.js +31 -31
  76. package/dist/page-tabs/index.js +5 -5
  77. package/dist/ui/index.d.ts +1 -1
  78. package/dist/ui/index.js +13 -13
  79. package/dist/ui.css +78 -10
  80. package/package.json +1 -1
  81. package/dist/ConfirmDialog-LYSSZSUD.js +0 -4
  82. package/dist/PdfViewer-HKO6P4SR.js +0 -5
  83. package/dist/chunk-72CQWN7O.js.map +0 -1
  84. package/dist/chunk-D276EMXS.js.map +0 -1
  85. package/dist/chunk-OLJDJYSU.js.map +0 -1
  86. package/dist/chunk-Q2MJVSJT.js +0 -7
  87. package/dist/chunk-QRL64J5F.js.map +0 -1
@@ -1,14 +1,14 @@
1
- import { Breadcrumbs } from './chunk-GIGV2ZRW.js';
2
- import { SidebarLayout } from './chunk-ET6ID4LP.js';
1
+ import { Breadcrumbs } from './chunk-5RPTS3BT.js';
2
+ import { SidebarLayout } from './chunk-R7QGMK6N.js';
3
3
  import { BrandMark } from './chunk-TRCWINHF.js';
4
- import { toast_default } from './chunk-4P44JXDS.js';
5
- import { useIsMobile, useShortcutLabel, useShellPrefs } from './chunk-2TPTHAKI.js';
6
- import { useFileIntake, humanSize, FileIntakeAlert } from './chunk-QAGQRNKI.js';
4
+ import { toast_default } from './chunk-UTYKLGGT.js';
5
+ import { useIsMobile, useShortcutLabel, useShellPrefs } from './chunk-HUBJAUGG.js';
6
+ import { useFileIntake, humanSize, FileIntakeAlert } from './chunk-YDHXWCCJ.js';
7
7
  import { iconButtonClasses, Button_default } from './chunk-RT6DSB5Y.js';
8
- import { PopupMenu, PopupMenuItem } from './chunk-QRL64J5F.js';
9
- import { registerModalEscapeInterceptor, onOverlayOpen, Z_LAYERS, useDismissPopupsOnOpen, useFocusTrap, useScrollLock } from './chunk-W622KQTD.js';
10
- import { glassStyle } from './chunk-D276EMXS.js';
11
- import { useShellLocale, useShellStrings, DEFAULT_SHELL_STRINGS, currentShellStrings, formatPlain, formatFixed, formatPercent, splitAround } from './chunk-72CQWN7O.js';
8
+ import { PopupMenu, PopupMenuDivider, PopupMenuLabel, itemLook } from './chunk-JOPU6WPY.js';
9
+ import { registerModalEscapeInterceptor, onOverlayOpen, Z_LAYERS, useDismissPopupsOnOpen, useFocusTrap, useScrollLock } from './chunk-I2TAAJHS.js';
10
+ import { glassStyle, glassFill } from './chunk-6XJEJWNJ.js';
11
+ import { useShellLocale, useShellStrings, DEFAULT_SHELL_STRINGS, currentShellStrings, formatPlain, formatFixed, formatPercent, splitAround } from './chunk-YE6GUDGP.js';
12
12
  import { useBrowserLayoutEffect, useBrowserValue, useBrowserValueOnce } from './chunk-IRWSRJ4K.js';
13
13
  import { forwardRef, useCallback, useState, useRef, useId, useEffect, createContext, useMemo, Children, isValidElement, cloneElement, useContext, Fragment as Fragment$1, Component, useSyncExternalStore, useLayoutEffect } from 'react';
14
14
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -133,13 +133,17 @@ var ACROSS = {
133
133
  left: ["top", "bottom"],
134
134
  right: ["top", "bottom"]
135
135
  };
136
- function placeBeside(anchor, size, side, bounds, gap) {
137
- const room = {
136
+ function roomAround(anchor, bounds, gap) {
137
+ return {
138
138
  top: anchor.top - gap - (bounds.top + VIEWPORT_MARGIN),
139
139
  bottom: bounds.bottom - VIEWPORT_MARGIN - (anchor.bottom + gap),
140
140
  left: anchor.left - gap - (bounds.left + VIEWPORT_MARGIN),
141
141
  right: bounds.right - VIEWPORT_MARGIN - (anchor.right + gap)
142
142
  };
143
+ }
144
+ var within = (value, lo, hi) => Math.max(lo, Math.min(value, hi));
145
+ function placeBeside(anchor, size, side, bounds, gap) {
146
+ const room = roomAround(anchor, bounds, gap);
143
147
  const spare = (s) => room[s] - (s === "top" || s === "bottom" ? size.height : size.width);
144
148
  const order = [side, OPPOSITE[side], ...ACROSS[side]];
145
149
  const chosen = order.find((s) => spare(s) >= 0) ?? order.reduce((best, s) => spare(s) > spare(best) ? s : best);
@@ -165,18 +169,94 @@ function placeBeside(anchor, size, side, bounds, gap) {
165
169
  top = centreY - size.height / 2;
166
170
  break;
167
171
  }
168
- const within = (value, lo, hi) => Math.max(lo, Math.min(value, hi));
169
172
  return {
170
173
  side: chosen,
171
174
  left: within(left, bounds.left + VIEWPORT_MARGIN, bounds.right - VIEWPORT_MARGIN - size.width),
172
175
  top: within(top, bounds.top + VIEWPORT_MARGIN, bounds.bottom - VIEWPORT_MARGIN - size.height)
173
176
  };
174
177
  }
178
+ function placeArrow(anchor, placed, size, inset, depth) {
179
+ const { side, left, top } = placed;
180
+ const right = left + size.width;
181
+ const bottom = top + size.height;
182
+ const clearance = {
183
+ top: anchor.top - bottom,
184
+ bottom: top - anchor.bottom,
185
+ left: anchor.left - right,
186
+ right: left - anchor.right
187
+ }[side];
188
+ if (clearance < depth) return null;
189
+ const along = (target, start, length) => length < 2 * inset ? start + length / 2 : Math.max(start + inset, Math.min(target, start + length - inset));
190
+ const centreX = (anchor.left + anchor.right) / 2;
191
+ const centreY = (anchor.top + anchor.bottom) / 2;
192
+ switch (side) {
193
+ case "top":
194
+ return { side, x: along(centreX, left, size.width), y: bottom };
195
+ case "bottom":
196
+ return { side, x: along(centreX, left, size.width), y: top };
197
+ case "left":
198
+ return { side, x: right, y: along(centreY, top, size.height) };
199
+ case "right":
200
+ return { side, x: left, y: along(centreY, top, size.height) };
201
+ }
202
+ }
203
+ function followAnchor(anchor, onMove, watch) {
204
+ let lastLeft = NaN, lastTop = NaN, lastRight = NaN, lastBottom = NaN, lastWatched = NaN;
205
+ const remember = () => {
206
+ const rect = anchor()?.getBoundingClientRect();
207
+ if (!rect) return false;
208
+ const watched = watch ? watch() : NaN;
209
+ const moved = rect.left !== lastLeft || rect.top !== lastTop || rect.right !== lastRight || rect.bottom !== lastBottom || watched !== lastWatched && !(Number.isNaN(watched) && Number.isNaN(lastWatched));
210
+ lastLeft = rect.left;
211
+ lastTop = rect.top;
212
+ lastRight = rect.right;
213
+ lastBottom = rect.bottom;
214
+ lastWatched = watched;
215
+ return moved;
216
+ };
217
+ remember();
218
+ const run = () => {
219
+ remember();
220
+ onMove();
221
+ };
222
+ let raf = requestAnimationFrame(function tick() {
223
+ if (remember()) onMove();
224
+ raf = requestAnimationFrame(tick);
225
+ });
226
+ window.addEventListener("scroll", run, true);
227
+ window.addEventListener("resize", run);
228
+ return () => {
229
+ cancelAnimationFrame(raf);
230
+ window.removeEventListener("scroll", run, true);
231
+ window.removeEventListener("resize", run);
232
+ };
233
+ }
234
+ function placeMenu({ trigger, menu, bounds, align, side }) {
235
+ const room = roomAround(trigger, bounds, MENU_GAP);
236
+ const other = side === "bottom" ? "top" : "bottom";
237
+ const chosen = menu.height > room[side] && (menu.height <= room[other] || room[other] > room[side]) ? other : side;
238
+ const maxHeight = Math.max(Math.min(menu.height, 96), room[chosen]);
239
+ const height = Math.min(menu.height, maxHeight);
240
+ const top = within(
241
+ chosen === "bottom" ? trigger.bottom + MENU_GAP : trigger.top - MENU_GAP - height,
242
+ bounds.top + VIEWPORT_MARGIN,
243
+ bounds.bottom - VIEWPORT_MARGIN - height
244
+ );
245
+ const maxWidth = Math.max(0, bounds.right - bounds.left - 2 * VIEWPORT_MARGIN);
246
+ const width = Math.min(menu.width, maxWidth);
247
+ const left = within(
248
+ align === "start" ? trigger.left : trigger.right - width,
249
+ bounds.left + VIEWPORT_MARGIN,
250
+ bounds.right - VIEWPORT_MARGIN - width
251
+ );
252
+ return { left, top, side: chosen, maxHeight, maxWidth };
253
+ }
175
254
  function useDropdownPosition(triggerRef, open, options = {}) {
176
255
  const {
177
256
  matchTriggerWidth = false,
178
257
  preferredMaxWidth = POPUP_MAX_WIDTH,
179
- preferredMaxHeight = MENU_MAX_HEIGHT
258
+ preferredMaxHeight = MENU_MAX_HEIGHT,
259
+ popupRef
180
260
  } = options;
181
261
  const [pos, setPos] = useState(null);
182
262
  useBrowserLayoutEffect(() => {
@@ -184,15 +264,10 @@ function useDropdownPosition(triggerRef, open, options = {}) {
184
264
  setPos(null);
185
265
  return;
186
266
  }
187
- let lastLeft = NaN, lastTop = NaN, lastRight = NaN, lastBottom = NaN;
188
267
  const compute = () => {
189
268
  const trigger = triggerRef.current;
190
269
  const rect = trigger?.getBoundingClientRect();
191
270
  if (!rect) return;
192
- lastLeft = rect.left;
193
- lastTop = rect.top;
194
- lastRight = rect.right;
195
- lastBottom = rect.bottom;
196
271
  const bounds = popupBounds(trigger);
197
272
  const spaceBelow = bounds.bottom - rect.bottom - MENU_GAP - VIEWPORT_MARGIN;
198
273
  const spaceAbove = rect.top - bounds.top - MENU_GAP - VIEWPORT_MARGIN;
@@ -212,6 +287,13 @@ function useDropdownPosition(triggerRef, open, options = {}) {
212
287
  Math.max(bounds.left + VIEWPORT_MARGIN, rect.left),
213
288
  bounds.right - VIEWPORT_MARGIN - width
214
289
  );
290
+ } else if (popupRef && bounds.right - VIEWPORT_MARGIN - rect.left < next.maxWidth && Math.min(rect.right, bounds.right - VIEWPORT_MARGIN) - bounds.left - VIEWPORT_MARGIN < next.maxWidth) {
291
+ const measured = popupRef.current?.offsetWidth ?? 0;
292
+ const width = measured > 0 ? Math.min(measured, next.maxWidth) : next.maxWidth;
293
+ next.left = Math.max(
294
+ bounds.left + VIEWPORT_MARGIN,
295
+ Math.min(rect.left, bounds.right - VIEWPORT_MARGIN - width)
296
+ );
215
297
  } else if (bounds.right - VIEWPORT_MARGIN - rect.left < next.maxWidth) {
216
298
  const rightEdge = Math.min(rect.right, bounds.right - VIEWPORT_MARGIN);
217
299
  next.right = window.innerWidth - rightEdge;
@@ -227,21 +309,12 @@ function useDropdownPosition(triggerRef, open, options = {}) {
227
309
  setPos(next);
228
310
  };
229
311
  compute();
230
- let raf = requestAnimationFrame(function tick() {
231
- const rect = triggerRef.current?.getBoundingClientRect();
232
- if (rect && (rect.left !== lastLeft || rect.top !== lastTop || rect.right !== lastRight || rect.bottom !== lastBottom)) {
233
- compute();
234
- }
235
- raf = requestAnimationFrame(tick);
236
- });
237
- window.addEventListener("scroll", compute, true);
238
- window.addEventListener("resize", compute);
239
- return () => {
240
- cancelAnimationFrame(raf);
241
- window.removeEventListener("scroll", compute, true);
242
- window.removeEventListener("resize", compute);
243
- };
244
- }, [open, triggerRef, matchTriggerWidth, preferredMaxWidth, preferredMaxHeight]);
312
+ return followAnchor(
313
+ () => triggerRef.current,
314
+ compute,
315
+ popupRef ? () => popupRef.current?.offsetWidth ?? NaN : void 0
316
+ );
317
+ }, [open, triggerRef, matchTriggerWidth, preferredMaxWidth, preferredMaxHeight, popupRef]);
245
318
  return pos;
246
319
  }
247
320
 
@@ -1577,6 +1650,22 @@ function calendarNames(locale) {
1577
1650
  localeNames.set(locale, names);
1578
1651
  return names;
1579
1652
  }
1653
+ var weekStarts = /* @__PURE__ */ new Map();
1654
+ function firstDayOfWeek(locale) {
1655
+ if (!locale) return 0;
1656
+ let first = weekStarts.get(locale);
1657
+ if (first === void 0) {
1658
+ first = 0;
1659
+ try {
1660
+ const tag = new Intl.Locale(locale);
1661
+ const info = typeof tag.getWeekInfo === "function" ? tag.getWeekInfo() : tag.weekInfo;
1662
+ if (info?.firstDay === 1) first = 1;
1663
+ } catch {
1664
+ }
1665
+ weekStarts.set(locale, first);
1666
+ }
1667
+ return first;
1668
+ }
1580
1669
  var pad = (n) => String(n).padStart(2, "0");
1581
1670
  function toKey(d) {
1582
1671
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
@@ -1618,7 +1707,7 @@ function Calendar({
1618
1707
  month,
1619
1708
  defaultMonth,
1620
1709
  onMonthChange,
1621
- weekStartsOn = 0,
1710
+ weekStartsOn: weekStartsOnProp,
1622
1711
  quickJump = true,
1623
1712
  "aria-label": ariaLabel,
1624
1713
  className = ""
@@ -1627,7 +1716,10 @@ function Calendar({
1627
1716
  const todayKey = useBrowserValue(readTodayKey, null);
1628
1717
  const today = fromKey(todayKey);
1629
1718
  const strings = useShellStrings().calendar;
1630
- const names = calendarNames(useShellLocale());
1719
+ const locale = useShellLocale();
1720
+ const names = calendarNames(locale);
1721
+ const localeWeekStart = useBrowserValue(() => firstDayOfWeek(locale), 0);
1722
+ const weekStartsOn = weekStartsOnProp ?? localeWeekStart;
1631
1723
  const openingMonth = () => {
1632
1724
  if (!today) return null;
1633
1725
  const here = monthKey(today);
@@ -1876,7 +1968,13 @@ function DateRangePicker({
1876
1968
  to,
1877
1969
  onChange,
1878
1970
  formatDisplay: formatDisplayProp,
1879
- clearable = true,
1971
+ clearable: clearableProp,
1972
+ required = false,
1973
+ name,
1974
+ id,
1975
+ "aria-labelledby": ariaLabelledBy,
1976
+ "aria-label": ariaLabel,
1977
+ weekStartsOn,
1880
1978
  placeholder: placeholderProp,
1881
1979
  fullWidth = false
1882
1980
  }) {
@@ -1884,16 +1982,44 @@ function DateRangePicker({
1884
1982
  const locale = useShellLocale();
1885
1983
  const formatDisplay = formatDisplayProp ?? (locale ? localeFormatDisplay(locale) : defaultFormatDisplay);
1886
1984
  const placeholder = placeholderProp ?? strings.placeholder;
1985
+ const clearable = clearableProp ?? !required;
1887
1986
  const [open, setOpen] = useState(false);
1888
1987
  const [tempFrom, setTempFrom] = useState(from);
1889
1988
  const [tempTo, setTempTo] = useState(to);
1890
1989
  const [activePreset, setActivePreset] = useState(null);
1891
1990
  const ref = useRef(null);
1991
+ const triggerRef = useRef(null);
1892
1992
  const panelRef = useRef(null);
1993
+ const panelId = useId();
1994
+ const descriptionId = useId();
1995
+ const [stacked, setStacked] = useState(false);
1893
1996
  const pos = useDropdownPosition(ref, open, {
1894
1997
  preferredMaxWidth: 520,
1895
- preferredMaxHeight: 560
1998
+ preferredMaxHeight: stacked ? 720 : 560,
1999
+ popupRef: panelRef
2000
+ });
2001
+ const sideRowRef = useRef(null);
2002
+ const sideWidth = useRef(null);
2003
+ useBrowserLayoutEffect(() => {
2004
+ const panel = panelRef.current;
2005
+ if (!open || !pos || !panel) return;
2006
+ const style = getComputedStyle(panel);
2007
+ const room = pos.maxWidth - (panel.offsetWidth - panel.clientWidth) - parseFloat(style.paddingLeft) - parseFloat(style.paddingRight);
2008
+ if (!stacked) {
2009
+ const natural = sideRowRef.current?.offsetWidth ?? 0;
2010
+ if (natural === 0) return;
2011
+ sideWidth.current = natural;
2012
+ if (natural > room + 0.5) setStacked(true);
2013
+ } else if (sideWidth.current !== null && sideWidth.current <= room) {
2014
+ setStacked(false);
2015
+ }
2016
+ });
2017
+ const [hasLabelElement, setHasLabelElement] = useState(false);
2018
+ useBrowserLayoutEffect(() => {
2019
+ const labelled = !!id && (triggerRef.current?.labels?.length ?? 0) > 0;
2020
+ if (labelled !== hasLabelElement) setHasLabelElement(labelled);
1896
2021
  });
2022
+ const namedElsewhere = !!ariaLabel || !!ariaLabelledBy || hasLabelElement;
1897
2023
  const now = /* @__PURE__ */ new Date();
1898
2024
  const [viewMonth, setViewMonth] = useState(() => monthKeyOf(from ? parseDate(from) : now));
1899
2025
  const displayDate = (s) => s ? formatDisplay(s) : "";
@@ -1973,6 +2099,37 @@ function DateRangePicker({
1973
2099
  setOpen(false);
1974
2100
  };
1975
2101
  const displayText = from && to ? `${displayDate(from)} \u2014 ${displayDate(to)}` : from ? strings.fromOnly(displayDate(from)) : to ? strings.toOnly(displayDate(to)) : "";
2102
+ const names = calendarNames(locale);
2103
+ const spoken = (iso) => {
2104
+ const d = fromKey(iso);
2105
+ return d ? names.longDate(d.getFullYear(), d.getMonth(), d.getDate()) : iso;
2106
+ };
2107
+ const description = from && to ? strings.range(spoken(from), spoken(to)) : from ? strings.fromOnly(spoken(from)) : to ? strings.toOnly(spoken(to)) : placeholder;
2108
+ const presetClass = (key) => stacked ? `rounded-md border px-2.5 py-1 text-sm transition-colors ${activePreset === key ? "border-blue-300 bg-blue-50 text-blue-700 font-medium" : "border-gray-200 text-gray-700 hover:bg-gray-50"}` : `text-left px-3 py-1.5 text-sm rounded-md transition-colors ${activePreset === key ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-700 hover:bg-gray-50"}`;
2109
+ const presets = /* @__PURE__ */ jsxs(Fragment, { children: [
2110
+ PRESETS.map((label) => /* @__PURE__ */ jsx("button", { type: "button", onClick: () => handlePreset(label), className: presetClass(label), children: strings[label] }, label)),
2111
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: () => setActivePreset("Custom"), className: presetClass("Custom"), children: strings.custom })
2112
+ ] });
2113
+ const calendar = (
2114
+ // The grid, its keyboard model and its ARIA all come from Calendar, which
2115
+ // is also what DatePicker draws — so a range and a single date look and
2116
+ // behave like the same control. This used to be 95 lines of hand-built
2117
+ // cells here with no arrow keys and a day whose accessible name was its
2118
+ // number.
2119
+ /* @__PURE__ */ jsx(
2120
+ Calendar,
2121
+ {
2122
+ mode: "range",
2123
+ value: tempFrom || null,
2124
+ endValue: tempTo || null,
2125
+ month: viewMonth,
2126
+ onMonthChange: setViewMonth,
2127
+ onSelect: handleCalendarSelect,
2128
+ weekStartsOn,
2129
+ "aria-label": strings.dialog
2130
+ }
2131
+ )
2132
+ );
1976
2133
  return /* @__PURE__ */ jsxs("div", { className: `relative${fullWidth ? " w-full" : ""}`, ref, children: [
1977
2134
  /* @__PURE__ */ jsxs(
1978
2135
  "div",
@@ -1982,13 +2139,20 @@ function DateRangePicker({
1982
2139
  /* @__PURE__ */ jsxs(
1983
2140
  "button",
1984
2141
  {
2142
+ ref: triggerRef,
1985
2143
  type: "button",
1986
2144
  onClick: handleOpen,
1987
2145
  "aria-haspopup": "dialog",
1988
2146
  "aria-expanded": open,
2147
+ id,
2148
+ "aria-label": ariaLabel,
2149
+ "aria-labelledby": ariaLabelledBy,
2150
+ "aria-describedby": namedElsewhere ? descriptionId : void 0,
2151
+ "aria-controls": open ? panelId : void 0,
2152
+ "aria-required": required || void 0,
1989
2153
  className: `inline-flex items-center gap-2 rosh-focus-ring${fullWidth ? " min-w-0 flex-1 justify-start" : ""}`,
1990
2154
  children: [
1991
- /* @__PURE__ */ jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" }) }),
2155
+ /* @__PURE__ */ jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" }) }),
1992
2156
  /* @__PURE__ */ jsx("span", { className: "truncate", children: displayText || placeholder })
1993
2157
  ]
1994
2158
  }
@@ -2006,13 +2170,20 @@ function DateRangePicker({
2006
2170
  ]
2007
2171
  }
2008
2172
  ),
2173
+ namedElsewhere && /* @__PURE__ */ jsx("span", { id: descriptionId, className: "sr-only", children: description }),
2174
+ name && /* @__PURE__ */ jsxs(Fragment, { children: [
2175
+ /* @__PURE__ */ jsx("input", { type: "hidden", name: name.from, value: from }),
2176
+ /* @__PURE__ */ jsx("input", { type: "hidden", name: name.to, value: to })
2177
+ ] }),
2009
2178
  open && createPortal(
2010
2179
  /* @__PURE__ */ jsxs(
2011
2180
  "div",
2012
2181
  {
2013
2182
  ref: panelRef,
2183
+ id: panelId,
2014
2184
  role: "dialog",
2015
2185
  "aria-label": strings.dialog,
2186
+ "data-layout": stacked ? "stacked" : "side",
2016
2187
  className: "fixed rounded-2xl p-4",
2017
2188
  style: {
2018
2189
  zIndex: Z_LAYERS.popup,
@@ -2022,8 +2193,9 @@ function DateRangePicker({
2022
2193
  bottom: pos?.bottom,
2023
2194
  // The panel states its own size. `max-content` is the calendar plus
2024
2195
  // the presets column at whatever font size the reader has, and the
2025
- // cap is what the owning window allows.
2026
- width: "max-content",
2196
+ // cap is what the owning window allows. Stacked, it is the cap
2197
+ // itself: the calendar fills it, and its days are bigger targets.
2198
+ width: stacked && pos ? pos.maxWidth : "max-content",
2027
2199
  maxWidth: pos?.maxWidth,
2028
2200
  maxHeight: pos?.maxHeight,
2029
2201
  overflowY: "auto",
@@ -2033,53 +2205,29 @@ function DateRangePicker({
2033
2205
  ...glassStyle()
2034
2206
  },
2035
2207
  children: [
2036
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 mb-3", children: [
2037
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2208
+ /* @__PURE__ */ jsxs("div", { className: stacked ? "mb-3 flex flex-wrap items-center gap-x-4 gap-y-2" : "flex items-center gap-3 mb-3", children: [
2209
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 whitespace-nowrap", children: [
2038
2210
  /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-500", children: strings.from }),
2039
2211
  /* @__PURE__ */ jsx("span", { className: `text-sm px-2 py-1 rounded border min-w-[90px] ${tempFrom ? "border-blue-300 bg-blue-50 text-blue-700" : "border-gray-200 bg-gray-50 text-gray-400"}`, children: tempFrom ? displayDate(tempFrom) : strings.start })
2040
2212
  ] }),
2041
- /* @__PURE__ */ jsx("span", { className: "text-gray-300", children: "\u2014" }),
2042
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2213
+ !stacked && /* @__PURE__ */ jsx("span", { className: "text-gray-300", children: "\u2014" }),
2214
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 whitespace-nowrap", children: [
2043
2215
  /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-500", children: strings.to }),
2044
2216
  /* @__PURE__ */ jsx("span", { className: `text-sm px-2 py-1 rounded border min-w-[90px] ${tempTo ? "border-blue-300 bg-blue-50 text-blue-700" : "border-gray-200 bg-gray-50 text-gray-400"}`, children: tempTo ? displayDate(tempTo) : strings.end })
2045
2217
  ] })
2046
2218
  ] }),
2047
- /* @__PURE__ */ jsxs("div", { className: "flex gap-4", children: [
2048
- /* @__PURE__ */ jsx("div", { className: "w-64", children: /* @__PURE__ */ jsx(
2049
- Calendar,
2050
- {
2051
- mode: "range",
2052
- value: tempFrom || null,
2053
- endValue: tempTo || null,
2054
- month: viewMonth,
2055
- onMonthChange: setViewMonth,
2056
- onSelect: handleCalendarSelect,
2057
- "aria-label": strings.dialog
2058
- }
2059
- ) }),
2060
- /* @__PURE__ */ jsxs("div", { className: "border-l border-gray-200 pl-4 flex flex-col gap-1 min-w-[130px]", children: [
2061
- PRESETS.map((label) => /* @__PURE__ */ jsx(
2062
- "button",
2063
- {
2064
- type: "button",
2065
- onClick: () => handlePreset(label),
2066
- className: `text-left px-3 py-1.5 text-sm rounded-md transition-colors ${activePreset === label ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-700 hover:bg-gray-50"}`,
2067
- children: strings[label]
2068
- },
2069
- label
2070
- )),
2071
- /* @__PURE__ */ jsx(
2072
- "button",
2073
- {
2074
- type: "button",
2075
- onClick: () => setActivePreset("Custom"),
2076
- className: `text-left px-3 py-1.5 text-sm rounded-md transition-colors ${activePreset === "Custom" ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-700 hover:bg-gray-50"}`,
2077
- children: strings.custom
2078
- }
2079
- )
2219
+ stacked ? /* @__PURE__ */ jsxs(Fragment, { children: [
2220
+ /* @__PURE__ */ jsx("div", { className: "mb-3 flex flex-wrap gap-1.5", children: presets }),
2221
+ /* @__PURE__ */ jsx("div", { className: "w-full", children: calendar })
2222
+ ] }) : (
2223
+ // `w-max`: the row is drawn at its natural width even in a panel
2224
+ // capped narrower, which is what the measurement above reads.
2225
+ /* @__PURE__ */ jsxs("div", { ref: sideRowRef, className: "flex w-max gap-4", children: [
2226
+ /* @__PURE__ */ jsx("div", { className: "w-64", children: calendar }),
2227
+ /* @__PURE__ */ jsx("div", { className: "border-l border-gray-200 pl-4 flex flex-col gap-1 min-w-[130px]", children: presets })
2080
2228
  ] })
2081
- ] }),
2082
- /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2 mt-4 pt-3 border-t border-gray-200", children: [
2229
+ ),
2230
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap justify-end gap-2 mt-4 pt-3 border-t border-gray-200", children: [
2083
2231
  clearable && /* @__PURE__ */ jsx("button", { type: "button", onClick: handleClear, className: "px-3 py-1.5 text-sm text-gray-500 hover:text-gray-700", children: strings.clear }),
2084
2232
  /* @__PURE__ */ jsx("button", { type: "button", onClick: () => setOpen(false), className: "px-3 py-1.5 text-sm text-gray-600 border border-gray-300 rounded-md hover:bg-gray-50", children: strings.cancel }),
2085
2233
  /* @__PURE__ */ jsx(
@@ -2133,6 +2281,7 @@ var TimePicker = forwardRef(function TimePicker2({ value, onChange, min, max, in
2133
2281
  });
2134
2282
  var TimePicker_default = TimePicker;
2135
2283
  var ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
2284
+ var GLOBAL_ATTRIBUTE = /^(aria|data)-/;
2136
2285
  function toInputValue2(value) {
2137
2286
  if (value === null || value === void 0 || value === "") return "";
2138
2287
  if (value instanceof Date) return Number.isNaN(value.getTime()) ? "" : toISODate(value);
@@ -2162,12 +2311,22 @@ var DatePicker = forwardRef(function DatePicker2({
2162
2311
  className = "",
2163
2312
  "aria-label": ariaLabel,
2164
2313
  "aria-describedby": describedBy,
2314
+ "aria-labelledby": labelledBy,
2165
2315
  id,
2166
2316
  name,
2167
2317
  disabled,
2168
2318
  placeholder,
2319
+ required,
2320
+ clearable: clearableProp,
2321
+ form,
2322
+ title,
2323
+ tabIndex,
2324
+ autoFocus,
2325
+ onFocus,
2326
+ onBlur,
2169
2327
  ...rest
2170
2328
  }, ref) {
2329
+ const clearable = clearableProp ?? !required;
2171
2330
  const current = toInputValue2(value);
2172
2331
  const lo = toInputValue2(min);
2173
2332
  const hi = toInputValue2(max);
@@ -2179,7 +2338,14 @@ var DatePicker = forwardRef(function DatePicker2({
2179
2338
  const triggerRef = useRef(null);
2180
2339
  const panelRef = useRef(null);
2181
2340
  const panelId = useId();
2182
- const pos = useDropdownPosition(triggerRef, open);
2341
+ const valueId = useId();
2342
+ const pos = useDropdownPosition(triggerRef, open, { popupRef: panelRef });
2343
+ const [hasLabelElement, setHasLabelElement] = useState(false);
2344
+ useBrowserLayoutEffect(() => {
2345
+ const labelled = !!id && (triggerRef.current?.labels?.length ?? 0) > 0;
2346
+ if (labelled !== hasLabelElement) setHasLabelElement(labelled);
2347
+ });
2348
+ const describeValue = !ariaLabel && (!!labelledBy || hasLabelElement);
2183
2349
  useEffect(() => {
2184
2350
  if (!open) return;
2185
2351
  const onPointerDown = (e) => {
@@ -2221,33 +2387,56 @@ var DatePicker = forwardRef(function DatePicker2({
2221
2387
  max: hi || void 0,
2222
2388
  onChange: (event) => onChange?.(fromInputValue(event.target.value)),
2223
2389
  className: inputClasses({ invalid, size, className }),
2390
+ "aria-labelledby": labelledBy,
2391
+ required,
2392
+ form,
2393
+ title,
2394
+ tabIndex,
2395
+ autoFocus,
2396
+ onFocus,
2397
+ onBlur,
2224
2398
  ...rest
2225
2399
  }
2226
2400
  );
2227
2401
  }
2402
+ const triggerAttributes = Object.fromEntries(
2403
+ Object.entries(rest).filter(([key]) => GLOBAL_ATTRIBUTE.test(key))
2404
+ );
2405
+ const todayKey = toISODate(/* @__PURE__ */ new Date());
2406
+ const todayAllowed = (!lo || todayKey >= lo) && (!hi || todayKey <= hi);
2407
+ const placeholderText = placeholder ?? strings.placeholder;
2228
2408
  return /* @__PURE__ */ jsxs("div", { ref: wrapRef, className: "relative", children: [
2229
- /* @__PURE__ */ jsx("input", { ref, type: "hidden", name, value: current }),
2409
+ /* @__PURE__ */ jsx("input", { ref, type: "hidden", name, form, value: current }),
2230
2410
  /* @__PURE__ */ jsxs(
2231
2411
  "button",
2232
2412
  {
2233
2413
  ref: triggerRef,
2234
2414
  type: "button",
2415
+ ...triggerAttributes,
2235
2416
  id,
2236
2417
  disabled,
2418
+ title,
2419
+ tabIndex,
2420
+ autoFocus,
2421
+ onFocus,
2422
+ onBlur,
2237
2423
  "aria-haspopup": "dialog",
2238
2424
  "aria-expanded": open,
2239
2425
  "aria-controls": open ? panelId : void 0,
2240
- "aria-describedby": describedBy,
2426
+ "aria-labelledby": labelledBy,
2427
+ "aria-describedby": [describeValue ? valueId : void 0, describedBy].filter(Boolean).join(" ") || void 0,
2241
2428
  "aria-invalid": invalid || void 0,
2429
+ "aria-required": required || void 0,
2242
2430
  "aria-label": ariaLabel ? `${ariaLabel}${current ? `, ${display(current, names)}` : ""}` : void 0,
2243
2431
  onClick: () => setOpen((o) => !o),
2244
2432
  className: `${inputClasses({ invalid, size, className })} flex items-center justify-between text-left`,
2245
2433
  children: [
2246
- /* @__PURE__ */ jsx("span", { className: current ? "text-gray-900" : "text-gray-400", children: current ? display(current, names) : placeholder ?? strings.placeholder }),
2434
+ /* @__PURE__ */ jsx("span", { className: current ? "text-gray-900" : "text-gray-400", children: current ? display(current, names) : placeholderText }),
2247
2435
  /* @__PURE__ */ jsx("svg", { className: "h-4 w-4 shrink-0 text-gray-400", fill: "none", stroke: "currentColor", strokeWidth: "1.75", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8 7V3m8 4V3M4 11h16M5 7h14a1 1 0 011 1v11a1 1 0 01-1 1H5a1 1 0 01-1-1V8a1 1 0 011-1z" }) })
2248
2436
  ]
2249
2437
  }
2250
2438
  ),
2439
+ describeValue && /* @__PURE__ */ jsx("span", { id: valueId, className: "sr-only", children: current ? display(current, names) : placeholderText }),
2251
2440
  open && createPortal(
2252
2441
  /* @__PURE__ */ jsxs(
2253
2442
  "div",
@@ -2263,6 +2452,9 @@ var DatePicker = forwardRef(function DatePicker2({
2263
2452
  right: pos?.right,
2264
2453
  top: pos?.top,
2265
2454
  bottom: pos?.bottom,
2455
+ // 288 px where it fits; narrower, never past the box's margins,
2456
+ // in a box that cannot hold that.
2457
+ maxWidth: pos?.maxWidth,
2266
2458
  // Hidden for the first paint until the layout effect measures the
2267
2459
  // trigger, so the panel never flashes at (0,0).
2268
2460
  visibility: pos ? void 0 : "hidden"
@@ -2282,8 +2474,8 @@ var DatePicker = forwardRef(function DatePicker2({
2282
2474
  }
2283
2475
  }
2284
2476
  ),
2285
- /* @__PURE__ */ jsxs("div", { className: "mt-2 flex justify-between border-t border-gray-100 pt-2", children: [
2286
- /* @__PURE__ */ jsx(
2477
+ (clearable || todayAllowed) && /* @__PURE__ */ jsxs("div", { className: "mt-2 flex justify-between border-t border-gray-100 pt-2", children: [
2478
+ clearable && /* @__PURE__ */ jsx(
2287
2479
  "button",
2288
2480
  {
2289
2481
  type: "button",
@@ -2296,7 +2488,7 @@ var DatePicker = forwardRef(function DatePicker2({
2296
2488
  children: strings.clear
2297
2489
  }
2298
2490
  ),
2299
- /* @__PURE__ */ jsx(
2491
+ todayAllowed && /* @__PURE__ */ jsx(
2300
2492
  "button",
2301
2493
  {
2302
2494
  type: "button",
@@ -2305,7 +2497,7 @@ var DatePicker = forwardRef(function DatePicker2({
2305
2497
  triggerRef.current?.focus();
2306
2498
  onChange?.(/* @__PURE__ */ new Date());
2307
2499
  },
2308
- className: "rounded-md px-2 py-1 text-sm font-medium text-blue-600 hover:bg-blue-50",
2500
+ className: "ml-auto rounded-md px-2 py-1 text-sm font-medium text-blue-600 hover:bg-blue-50",
2309
2501
  children: strings.today
2310
2502
  }
2311
2503
  )
@@ -4269,12 +4461,15 @@ function Accordion({
4269
4461
  }) });
4270
4462
  }
4271
4463
  var SIDE_POS = {
4272
- top: "bottom-full left-1/2 -translate-x-1/2 mb-1.5",
4273
- bottom: "top-full left-1/2 -translate-x-1/2 mt-1.5",
4274
- left: "right-full top-1/2 -translate-y-1/2 mr-1.5",
4275
- right: "left-full top-1/2 -translate-y-1/2 ml-1.5"
4464
+ top: "bottom-full left-1/2 -translate-x-1/2 mb-3",
4465
+ bottom: "top-full left-1/2 -translate-x-1/2 mt-3",
4466
+ left: "right-full top-1/2 -translate-y-1/2 mr-3",
4467
+ right: "left-full top-1/2 -translate-y-1/2 ml-3"
4276
4468
  };
4277
4469
  var GAP2 = 6;
4470
+ var ARROW_DEPTH = 6;
4471
+ var ARROW_INSET = 16;
4472
+ var samePlace = (a, b) => a.left === b.left && a.top === b.top && a.maxWidth === b.maxWidth && a.maxHeight === b.maxHeight && a.side === b.side && a.arrow?.left === b.arrow?.left && a.arrow?.top === b.arrow?.top;
4278
4473
  function Tooltip({ content, side = "top", delay = 200, children }) {
4279
4474
  const [show, setShow] = useState(false);
4280
4475
  const [placed, setPlaced] = useState(null);
@@ -4301,13 +4496,23 @@ function Tooltip({ content, side = "top", delay = 200, children }) {
4301
4496
  if (!wrap || !tip) return;
4302
4497
  const bounds = popupBounds(wrap);
4303
4498
  const maxWidth = Math.max(0, bounds.right - bounds.left - 2 * VIEWPORT_MARGIN);
4499
+ const maxHeight = Math.max(0, bounds.bottom - bounds.top - 2 * VIEWPORT_MARGIN);
4304
4500
  tip.style.maxWidth = `${maxWidth}px`;
4501
+ tip.style.maxHeight = `${maxHeight}px`;
4305
4502
  const size = tip.getBoundingClientRect();
4306
4503
  if (size.width <= 0 || size.height <= 0) return;
4307
4504
  const anchor = wrap.getBoundingClientRect();
4308
- const at = placeBeside(anchor, size, side, bounds, GAP2);
4309
- const next = { left: at.left - anchor.left, top: at.top - anchor.top, maxWidth };
4310
- setPlaced((prev) => prev && prev.left === next.left && prev.top === next.top && prev.maxWidth === next.maxWidth ? prev : next);
4505
+ const at = placeBeside(anchor, size, side, bounds, GAP2 + ARROW_DEPTH);
4506
+ const point = placeArrow(anchor, at, size, ARROW_INSET, ARROW_DEPTH);
4507
+ const next = {
4508
+ left: at.left - anchor.left,
4509
+ top: at.top - anchor.top,
4510
+ maxWidth,
4511
+ maxHeight,
4512
+ side: at.side,
4513
+ arrow: point && { left: point.x - anchor.left, top: point.y - anchor.top }
4514
+ };
4515
+ setPlaced((prev) => prev && samePlace(prev, next) ? prev : next);
4311
4516
  };
4312
4517
  place();
4313
4518
  window.addEventListener("scroll", place, true);
@@ -4329,6 +4534,8 @@ function Tooltip({ content, side = "top", delay = 200, children }) {
4329
4534
  const trigger = isValidElement(children) ? cloneElement(children, {
4330
4535
  "aria-describedby": [children.props["aria-describedby"], describedBy].filter(Boolean).join(" ") || void 0
4331
4536
  }) : children;
4537
+ const glass = show ? glassStyle() : void 0;
4538
+ const fill = show ? glassFill() : void 0;
4332
4539
  return /* @__PURE__ */ jsxs(
4333
4540
  "span",
4334
4541
  {
@@ -4347,6 +4554,8 @@ function Tooltip({ content, side = "top", delay = 200, children }) {
4347
4554
  // its window is wide wraps inside it instead of running past both
4348
4555
  // edges. `whitespace-normal` and `text-start` so a trigger inside a
4349
4556
  // `nowrap` or right-aligned cell does not hand the bubble its own.
4557
+ // `box-border` so the caps measure the whole bubble, padding and
4558
+ // border included, in a host without Tailwind's preflight.
4350
4559
  // Nothing here animates, so there is no motion to reduce.
4351
4560
  /* @__PURE__ */ jsx(
4352
4561
  "span",
@@ -4354,13 +4563,46 @@ function Tooltip({ content, side = "top", delay = 200, children }) {
4354
4563
  ref: tipRef,
4355
4564
  id,
4356
4565
  role: "tooltip",
4357
- className: `pointer-events-none absolute z-[300] w-max whitespace-normal break-words text-start rounded-md px-2 py-1 text-xs text-gray-800 ${placed ? "" : SIDE_POS[side]}`,
4566
+ className: `pointer-events-none absolute z-[300] box-border w-max overflow-hidden whitespace-normal break-words text-start rounded-md px-2 py-1 text-xs text-gray-800 ${placed ? "" : SIDE_POS[side]}`,
4358
4567
  style: {
4359
- ...glassStyle(),
4360
- ...placed && { left: placed.left, top: placed.top, maxWidth: placed.maxWidth }
4568
+ ...glass,
4569
+ ...placed && {
4570
+ left: placed.left,
4571
+ top: placed.top,
4572
+ maxWidth: placed.maxWidth,
4573
+ maxHeight: placed.maxHeight
4574
+ }
4361
4575
  },
4362
4576
  children: content
4363
4577
  }
4578
+ ),
4579
+ show && (!placed || placed.arrow) && // The arrow is the bubble's SIBLING, not its child: the bubble is
4580
+ // `overflow: hidden` for its height cap, and an arrow inside it would
4581
+ // be cut off at the very edge it is meant to stand out from. Drawn after
4582
+ // the bubble on the same layer, so it lies over the bubble's border
4583
+ // where the two meet and there is no seam.
4584
+ //
4585
+ // `data-side` is the side the BUBBLE is on, after any flip; ui.css
4586
+ // turns it into which way the arrow points and which two of its edges
4587
+ // carry the border. Unmeasured, it is the side asked for and ui.css
4588
+ // centres the arrow there, as `SIDE_POS` centres the bubble.
4589
+ //
4590
+ // Decorative: the bubble's text is the description, and the arrow says
4591
+ // nothing a screen reader needs.
4592
+ /* @__PURE__ */ jsx(
4593
+ "span",
4594
+ {
4595
+ "aria-hidden": "true",
4596
+ className: "rosh-tooltip-arrow",
4597
+ "data-side": placed?.side ?? side,
4598
+ style: {
4599
+ background: fill,
4600
+ // The bubble's border as one value, for ui.css to put on the two
4601
+ // edges that face outward — the side's own rule picks which.
4602
+ ["--rosh-tooltip-edge"]: glass?.border,
4603
+ ...placed?.arrow && { left: placed.arrow.left, top: placed.arrow.top }
4604
+ }
4605
+ }
4364
4606
  )
4365
4607
  ]
4366
4608
  }
@@ -8419,6 +8661,12 @@ function TopNav({ items, activeKey, onSelect, brand, actions, className }) {
8419
8661
  }
8420
8662
  );
8421
8663
  }
8664
+ var TRIGGER_CLASS = "inline-flex items-center justify-center rounded-md text-gray-600 transition-colors hover:bg-gray-100 hover:text-gray-900 rosh-focus-ring focus-visible:ring-2 focus-visible:ring-[color:var(--rosh-focus-ring-solid)] disabled:cursor-not-allowed disabled:opacity-60";
8665
+ var OWNS_Z = /(^|[\s:])!?z-/;
8666
+ var TYPEAHEAD_MS = 500;
8667
+ var CHECK = /* @__PURE__ */ jsx("svg", { "aria-hidden": true, className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M4.5 12.75l6 6 9-13.5" }) });
8668
+ var isLink = (entry) => entry.type === "link" || entry.type === void 0 && typeof entry.href === "string";
8669
+ var isFocusable = (entry) => !!entry && entry.type !== "label" && entry.type !== "divider" && !entry.disabled;
8422
8670
  function DropdownMenu({
8423
8671
  trigger,
8424
8672
  items,
@@ -8426,35 +8674,84 @@ function DropdownMenu({
8426
8674
  side = "bottom",
8427
8675
  "aria-label": ariaLabel,
8428
8676
  className = "",
8677
+ triggerClassName,
8678
+ menuClassName = "",
8679
+ minWidth = 180,
8680
+ linkAs,
8429
8681
  disabled
8430
8682
  }) {
8431
8683
  const [open, setOpen] = useState(false);
8432
- const [active, setActive] = useState(0);
8684
+ const [active, setActive] = useState(-1);
8433
8685
  const wrapRef = useRef(null);
8434
8686
  const triggerRef = useRef(null);
8435
- const itemRefs = useRef([]);
8687
+ const menuRef = useRef(null);
8688
+ const typed = useRef({ text: "", at: 0 });
8436
8689
  const menuId = useId();
8690
+ const triggerId = useId();
8437
8691
  const close = useCallback((restoreFocus) => {
8438
8692
  setOpen(false);
8439
8693
  if (restoreFocus) triggerRef.current?.focus();
8440
8694
  }, []);
8441
- const enabledFrom = (from, step) => {
8442
- for (let i = 0; i < items.length; i += 1) {
8443
- const at = ((from + step * i) % items.length + items.length) % items.length;
8444
- if (!items[at]?.disabled) return at;
8695
+ const focusableFrom = (from, step) => {
8696
+ const n = items.length;
8697
+ for (let i = 0; i < n; i += 1) {
8698
+ const at = ((from + step * i) % n + n) % n;
8699
+ if (isFocusable(items[at])) return at;
8445
8700
  }
8446
- return from;
8701
+ return -1;
8447
8702
  };
8703
+ const surface = () => menuRef.current?.closest("[data-popup-menu-tree]") ?? null;
8448
8704
  useEffect(() => {
8449
8705
  if (!open) return;
8450
8706
  const onPointerDown = (e) => {
8451
- if (!wrapRef.current?.contains(e.target)) close(false);
8707
+ const target = e.target;
8708
+ if (wrapRef.current?.contains(target) || surface()?.contains(target)) return;
8709
+ close(false);
8452
8710
  };
8453
8711
  document.addEventListener("pointerdown", onPointerDown, true);
8454
- return () => document.removeEventListener("pointerdown", onPointerDown, true);
8712
+ const offOverlay = onOverlayOpen(() => close(false));
8713
+ return () => {
8714
+ document.removeEventListener("pointerdown", onPointerDown, true);
8715
+ offOverlay();
8716
+ };
8455
8717
  }, [open, close]);
8718
+ const place = useCallback(() => {
8719
+ const el = surface();
8720
+ const anchor = triggerRef.current;
8721
+ if (!el || !anchor) return;
8722
+ const s = el.style;
8723
+ s.left = "0px";
8724
+ s.top = "0px";
8725
+ s.maxWidth = "none";
8726
+ s.maxHeight = "none";
8727
+ const size = { width: el.offsetWidth, height: el.offsetHeight };
8728
+ const at = placeMenu({
8729
+ trigger: anchor.getBoundingClientRect(),
8730
+ menu: size,
8731
+ bounds: popupBounds(anchor),
8732
+ align,
8733
+ side
8734
+ });
8735
+ s.left = `${at.left}px`;
8736
+ s.top = `${at.top}px`;
8737
+ s.maxWidth = `${at.maxWidth}px`;
8738
+ s.maxHeight = `${at.maxHeight}px`;
8739
+ s.overflowY = size.height > at.maxHeight ? "auto" : "";
8740
+ el.dataset.side = at.side;
8741
+ el.dataset.align = align;
8742
+ }, [align, side]);
8743
+ useBrowserLayoutEffect(() => {
8744
+ if (open) place();
8745
+ });
8746
+ useEffect(() => {
8747
+ if (!open) return;
8748
+ return followAnchor(() => triggerRef.current, place);
8749
+ }, [open, place]);
8456
8750
  useEffect(() => {
8457
- if (open) itemRefs.current[active]?.focus();
8751
+ if (!open) return;
8752
+ const menu = menuRef.current;
8753
+ const target = isFocusable(items[active]) ? menu?.querySelector(`[data-dropdown-index="${active}"]`) : null;
8754
+ (target ?? menu)?.focus({ preventScroll: true });
8458
8755
  }, [open, active]);
8459
8756
  useEffect(() => {
8460
8757
  if (!open) return;
@@ -8471,80 +8768,212 @@ function DropdownMenu({
8471
8768
  const onTriggerKeyDown = (e) => {
8472
8769
  if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
8473
8770
  e.preventDefault();
8474
- openAt(enabledFrom(0, 1));
8771
+ openAt(focusableFrom(0, 1));
8475
8772
  } else if (e.key === "ArrowUp") {
8476
8773
  e.preventDefault();
8477
- openAt(enabledFrom(items.length - 1, -1));
8774
+ openAt(focusableFrom(items.length - 1, -1));
8775
+ }
8776
+ };
8777
+ const typeahead = (e) => {
8778
+ const now = Date.now();
8779
+ const char = e.key.toLowerCase();
8780
+ const text = now - typed.current.at < TYPEAHEAD_MS ? typed.current.text + char : char;
8781
+ typed.current = { text, at: now };
8782
+ const repeated = [...text].every((c) => c === text[0]);
8783
+ const query = repeated ? text[0] : text;
8784
+ const from = repeated ? active + 1 : Math.max(active, 0);
8785
+ const menu = menuRef.current;
8786
+ const n = items.length;
8787
+ for (let i = 0; i < n; i += 1) {
8788
+ const at = ((from + i) % n + n) % n;
8789
+ if (!isFocusable(items[at])) continue;
8790
+ const label = menu?.querySelector(`[data-dropdown-index="${at}"]`)?.textContent?.trim().toLowerCase() ?? "";
8791
+ if (label.startsWith(query)) {
8792
+ e.preventDefault();
8793
+ setActive(at);
8794
+ return;
8795
+ }
8478
8796
  }
8479
8797
  };
8480
8798
  const onMenuKeyDown = (e) => {
8481
8799
  if (e.key === "ArrowDown") {
8482
8800
  e.preventDefault();
8483
- setActive(enabledFrom(active + 1, 1));
8801
+ setActive(focusableFrom(active + 1, 1));
8484
8802
  } else if (e.key === "ArrowUp") {
8485
8803
  e.preventDefault();
8486
- setActive(enabledFrom(active - 1, -1));
8804
+ setActive(focusableFrom(active - 1, -1));
8487
8805
  } else if (e.key === "Home") {
8488
8806
  e.preventDefault();
8489
- setActive(enabledFrom(0, 1));
8807
+ setActive(focusableFrom(0, 1));
8490
8808
  } else if (e.key === "End") {
8491
8809
  e.preventDefault();
8492
- setActive(enabledFrom(items.length - 1, -1));
8810
+ setActive(focusableFrom(items.length - 1, -1));
8493
8811
  } else if (e.key === "Tab") {
8494
8812
  e.preventDefault();
8495
8813
  close(true);
8814
+ } else if (e.key === " ") {
8815
+ const target = e.target;
8816
+ if (target.matches?.("a[href]")) {
8817
+ e.preventDefault();
8818
+ target.click();
8819
+ }
8820
+ } else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
8821
+ typeahead(e);
8496
8822
  }
8497
8823
  };
8498
- const select = (item) => {
8499
- if (item.disabled) return;
8824
+ const choose = (entry) => {
8825
+ if (entry.disabled) return;
8500
8826
  close(true);
8501
- item.onSelect();
8827
+ entry.onSelect();
8828
+ };
8829
+ const Link = linkAs ?? "a";
8830
+ const rowProps = (i, entry) => ({
8831
+ "data-dropdown-index": i,
8832
+ // One tab stop for the whole menu; the arrows move inside it.
8833
+ tabIndex: i === active ? 0 : -1,
8834
+ onMouseEnter: () => {
8835
+ if (!entry.disabled) setActive(i);
8836
+ }
8837
+ });
8838
+ const renderEntry = (entry, i) => {
8839
+ if (entry.type === "divider") {
8840
+ return /* @__PURE__ */ jsx("div", { role: "separator", children: /* @__PURE__ */ jsx(PopupMenuDivider, {}) }, entry.key);
8841
+ }
8842
+ if (entry.type === "label") {
8843
+ return /* @__PURE__ */ jsx("div", { id: `${menuId}-label-${i}`, children: /* @__PURE__ */ jsx(PopupMenuLabel, { children: entry.label }) }, entry.key);
8844
+ }
8845
+ if (entry.type === "radio") {
8846
+ const look2 = itemLook(false, entry.disabled, "");
8847
+ return /* @__PURE__ */ jsxs(
8848
+ "button",
8849
+ {
8850
+ type: "button",
8851
+ role: "menuitemradio",
8852
+ "aria-checked": entry.checked,
8853
+ disabled: entry.disabled,
8854
+ className: look2.className,
8855
+ style: look2.style,
8856
+ onClick: () => choose(entry),
8857
+ ...rowProps(i, entry),
8858
+ children: [
8859
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "inline-flex h-4 w-4 shrink-0 items-center justify-center", children: entry.checked && CHECK }),
8860
+ entry.icon,
8861
+ entry.label
8862
+ ]
8863
+ },
8864
+ entry.key
8865
+ );
8866
+ }
8867
+ if (isLink(entry)) {
8868
+ const look2 = itemLook(false, entry.disabled, `no-underline ${entry.current ? "font-medium" : ""}`);
8869
+ if (entry.disabled) {
8870
+ return /* @__PURE__ */ jsxs("a", { role: "menuitem", "aria-disabled": "true", className: look2.className, style: look2.style, ...rowProps(i, entry), children: [
8871
+ entry.icon,
8872
+ entry.label
8873
+ ] }, entry.key);
8874
+ }
8875
+ return /* @__PURE__ */ jsxs(
8876
+ Link,
8877
+ {
8878
+ href: entry.href,
8879
+ role: "menuitem",
8880
+ "aria-current": entry.current ? "page" : void 0,
8881
+ className: look2.className,
8882
+ style: look2.style,
8883
+ onClick: () => close(true),
8884
+ ...rowProps(i, entry),
8885
+ children: [
8886
+ entry.icon,
8887
+ entry.label
8888
+ ]
8889
+ },
8890
+ entry.key
8891
+ );
8892
+ }
8893
+ const look = itemLook(entry.danger, entry.disabled, "");
8894
+ return /* @__PURE__ */ jsxs(
8895
+ "button",
8896
+ {
8897
+ type: "button",
8898
+ role: "menuitem",
8899
+ disabled: entry.disabled,
8900
+ className: look.className,
8901
+ style: look.style,
8902
+ onClick: () => choose(entry),
8903
+ ...rowProps(i, entry),
8904
+ children: [
8905
+ entry.icon,
8906
+ entry.label
8907
+ ]
8908
+ },
8909
+ entry.key
8910
+ );
8911
+ };
8912
+ const renderEntries = () => {
8913
+ const out = [];
8914
+ for (let i = 0; i < items.length; ) {
8915
+ const entry = items[i];
8916
+ if (entry.type !== "radio") {
8917
+ out.push(renderEntry(entry, i));
8918
+ i += 1;
8919
+ continue;
8920
+ }
8921
+ const start = i;
8922
+ const run = [];
8923
+ while (i < items.length && items[i].type === "radio") {
8924
+ run.push(renderEntry(items[i], i));
8925
+ i += 1;
8926
+ }
8927
+ const heading = items[start - 1]?.type === "label" ? `${menuId}-label-${start - 1}` : void 0;
8928
+ out.push(/* @__PURE__ */ jsx("div", { role: "group", "aria-labelledby": heading, children: run }, `group:${entry.key}`));
8929
+ }
8930
+ return out;
8931
+ };
8932
+ const menuStyle = {
8933
+ // The popup layer, as every portalled kit popup: above dialogs and the
8934
+ // window stack, so a menu opened in either is drawn over it. A caller that
8935
+ // layered it with a `z-…` class keeps its own.
8936
+ ...OWNS_Z.test(menuClassName) ? {} : { zIndex: Z_LAYERS.popup },
8937
+ minWidth
8502
8938
  };
8503
8939
  return /* @__PURE__ */ jsxs("div", { ref: wrapRef, className: `relative inline-flex ${className}`.trim(), children: [
8504
8940
  /* @__PURE__ */ jsx(
8505
8941
  "button",
8506
8942
  {
8507
8943
  ref: triggerRef,
8944
+ id: triggerId,
8508
8945
  type: "button",
8509
8946
  "aria-haspopup": "menu",
8510
8947
  "aria-expanded": open,
8511
8948
  "aria-controls": open ? menuId : void 0,
8512
8949
  "aria-label": ariaLabel,
8513
8950
  disabled,
8514
- onClick: () => open ? close(false) : openAt(enabledFrom(0, 1)),
8951
+ onClick: () => open ? close(false) : openAt(focusableFrom(0, 1)),
8515
8952
  onKeyDown: onTriggerKeyDown,
8516
- className: "inline-flex items-center justify-center rounded-md text-gray-600 transition-colors hover:bg-gray-100 hover:text-gray-900 rosh-focus-ring focus-visible:ring-2 focus-visible:ring-[color:var(--rosh-focus-ring-solid)] disabled:cursor-not-allowed disabled:opacity-60",
8953
+ className: triggerClassName ?? TRIGGER_CLASS,
8517
8954
  children: trigger
8518
8955
  }
8519
8956
  ),
8520
- open && /* @__PURE__ */ jsx(
8957
+ open && // No `onClose`: PopupMenu's own dismissal calls the same callback for
8958
+ // Escape and for a click elsewhere, and those want opposite things.
8959
+ // Escape is the user putting the menu away, so focus goes back to the
8960
+ // trigger; a click elsewhere is them going somewhere, and dragging
8961
+ // focus back would take them off what they just clicked. The handlers
8962
+ // above tell the two apart.
8963
+ /* @__PURE__ */ jsx(PopupMenu, { portal: true, className: menuClassName, style: menuStyle, children: /* @__PURE__ */ jsx(
8521
8964
  "div",
8522
8965
  {
8523
- className: `absolute z-50 ${side === "top" ? "bottom-full mb-1" : "top-full mt-1"} ${align === "end" ? "right-0" : "left-0"}`,
8966
+ ref: menuRef,
8967
+ id: menuId,
8968
+ role: "menu",
8969
+ "aria-orientation": "vertical",
8970
+ "aria-label": ariaLabel,
8971
+ "aria-labelledby": ariaLabel ? void 0 : triggerId,
8972
+ tabIndex: -1,
8524
8973
  onKeyDown: onMenuKeyDown,
8525
- children: /* @__PURE__ */ jsx(PopupMenu, { portal: false, minWidth: 180, children: /* @__PURE__ */ jsx("div", { id: menuId, role: "menu", "aria-orientation": "vertical", "aria-label": ariaLabel, children: items.map((item, i) => /* @__PURE__ */ jsxs(
8526
- PopupMenuItem,
8527
- {
8528
- ref: (el) => {
8529
- itemRefs.current[i] = el;
8530
- },
8531
- role: "menuitem",
8532
- tabIndex: i === active ? 0 : -1,
8533
- danger: item.danger,
8534
- disabled: item.disabled,
8535
- onMouseEnter: () => {
8536
- if (!item.disabled) setActive(i);
8537
- },
8538
- onClick: () => select(item),
8539
- children: [
8540
- item.icon,
8541
- item.label
8542
- ]
8543
- },
8544
- item.key
8545
- )) }) })
8974
+ children: renderEntries()
8546
8975
  }
8547
- )
8976
+ ) })
8548
8977
  ] });
8549
8978
  }
8550
8979
  var APP_UPDATE_POLL_MS = 6e4;
@@ -13673,6 +14102,6 @@ function ChordChart({
13673
14102
  ] });
13674
14103
  }
13675
14104
 
13676
- export { APP_UPDATE_POLL_MS, Accordion, AppUpdateBanner, AttachButton, AttachmentDropZone, AttachmentList, AuthScreen, Avatar, AvatarGroup, Banner, BarChart, BoxPlotChart, BrandAssetEditor, BudgetBar, CHART_INK, Calendar, CandlestickChart, Card, CartesianPlot, ChartBrush, ChartDefs, ChartDot, ChartFrame, ChartHighlightProvider, ChartSkeleton, ChartTooltip, ChatTemplate, Checkbox_default, CheckoutTemplate, ChordChart, ColoredBadge, ColumnChart, ComposerAttachments, ContainerFillChart, CountBadge, DAY_MS, DashboardTemplate, DataTable, DataTablePage, DatePicker_default, DateRangePicker, DateTimePicker_default, DescriptionList, Divider, DonutChart, Drawer, DropdownMenu, EmailTemplate, EmptyState, ErrorBoundary, ErrorPage, FilePicker_default, FormErrorSummary, FormField, FormLayoutPage, FunnelChart, GROUP_COLORS, GROUP_COLORS_SOLID, GalleryTemplate, GlobalSearch, Grid, HeatmapChart, HelpCenter, HistogramChart, INPUT_BASE, INPUT_SIZES, IconButton_default, Inline, InputNumber_default, Input_default, Kanban, Label, LineChart, ListFooter, ListLoadError, MAX_FRACTION_DIGITS, MENU_MAX_HEIGHT, MOTION, Markdown, MediaUploadField, MediaUploadGrid, Meter, MetricBar, MilestoneTimeline, NativeSelect, NumericKeypad, POPUP_MAX_WIDTH, POST_PRODUCTION_STATUSES, PageHeader, Pagination, PaperclipGlyph, Paragraph, PieChart, PortalBrandingProvider, ProductionTimeline, RADAR_SERIES_CAP, RadarChart, RadialBarChart, RadioGroup, Radio_default, RangeChart, RankedBars, SCATTER_SERIES_CAP, SERIES_SLOT_COUNT, SERIES_VARS, STAGES, STATUS_VARS, SankeyChart, ScatterChart, SearchableSelect, Segmented, Select_default, SettingRow, SidebarActionButton, SidebarGroupLabel, SidebarNavItem, Skeleton, Snippet, Sparkline, Stack, StatCard, StatTile, Statistic, StatusBadge, StatusBadgeProvider, Stepper, SunburstChart, Switch_default, Tabs, TagInput, Text, Textarea_default, TileButton_default, TimePicker_default, TimeSeriesChart, TimelineTrack, Title, Tooltip, TopNav, TreemapChart, WaterfallChart, angleScale, appendKey, applyThemePrefs, arcPath, areaBetween, areaFrom, autoHighlightIndex, backspace, bandScale, binValues, budgetState, bumpPath, calcOverall, calcReportOverall, copyToClipboard, curvePath, dashFor, fillFor, fillId, firstEnabledIndex, fmtSliderDate, formatDate, fromKey, glowId, groundId, groupColors, highlightOpacity, inputClasses, isSeverityTone, ladderScale, lastEnabledIndex, linearPath, linearScale, logScale, maskId, matchTypeahead, mediaFileName, monotonePath, nextEnabledIndex, niceMax, polygonPoints, popupBounds, radiusScale, resolvePortalBrandAsset, resolveSeriesColor, resolveTheme, selectionAt, seriesColor, severityOf, splinePath, squarify, stagger, stepPath, tabButtonId, tabPanelId, toDayMs, toISODate, toKey, useAppUpdate, useClickOutside, useDropdownPosition, useHighlight, usePlotWidth, usePortalBranding, useProductionTimeline, useTheme };
13677
- //# sourceMappingURL=chunk-OLJDJYSU.js.map
13678
- //# sourceMappingURL=chunk-OLJDJYSU.js.map
14105
+ export { APP_UPDATE_POLL_MS, Accordion, AppUpdateBanner, AttachButton, AttachmentDropZone, AttachmentList, AuthScreen, Avatar, AvatarGroup, Banner, BarChart, BoxPlotChart, BrandAssetEditor, BudgetBar, CHART_INK, Calendar, CandlestickChart, Card, CartesianPlot, ChartBrush, ChartDefs, ChartDot, ChartFrame, ChartHighlightProvider, ChartSkeleton, ChartTooltip, ChatTemplate, Checkbox_default, CheckoutTemplate, ChordChart, ColoredBadge, ColumnChart, ComposerAttachments, ContainerFillChart, CountBadge, DAY_MS, DashboardTemplate, DataTable, DataTablePage, DatePicker_default, DateRangePicker, DateTimePicker_default, DescriptionList, Divider, DonutChart, Drawer, DropdownMenu, EmailTemplate, EmptyState, ErrorBoundary, ErrorPage, FilePicker_default, FormErrorSummary, FormField, FormLayoutPage, FunnelChart, GROUP_COLORS, GROUP_COLORS_SOLID, GalleryTemplate, GlobalSearch, Grid, HeatmapChart, HelpCenter, HistogramChart, INPUT_BASE, INPUT_SIZES, IconButton_default, Inline, InputNumber_default, Input_default, Kanban, Label, LineChart, ListFooter, ListLoadError, MAX_FRACTION_DIGITS, MENU_MAX_HEIGHT, MOTION, Markdown, MediaUploadField, MediaUploadGrid, Meter, MetricBar, MilestoneTimeline, NativeSelect, NumericKeypad, POPUP_MAX_WIDTH, POST_PRODUCTION_STATUSES, PageHeader, Pagination, PaperclipGlyph, Paragraph, PieChart, PortalBrandingProvider, ProductionTimeline, RADAR_SERIES_CAP, RadarChart, RadialBarChart, RadioGroup, Radio_default, RangeChart, RankedBars, SCATTER_SERIES_CAP, SERIES_SLOT_COUNT, SERIES_VARS, STAGES, STATUS_VARS, SankeyChart, ScatterChart, SearchableSelect, Segmented, Select_default, SettingRow, SidebarActionButton, SidebarGroupLabel, SidebarNavItem, Skeleton, Snippet, Sparkline, Stack, StatCard, StatTile, Statistic, StatusBadge, StatusBadgeProvider, Stepper, SunburstChart, Switch_default, Tabs, TagInput, Text, Textarea_default, TileButton_default, TimePicker_default, TimeSeriesChart, TimelineTrack, Title, Tooltip, TopNav, TreemapChart, WaterfallChart, angleScale, appendKey, applyThemePrefs, arcPath, areaBetween, areaFrom, autoHighlightIndex, backspace, bandScale, binValues, budgetState, bumpPath, calcOverall, calcReportOverall, copyToClipboard, curvePath, dashFor, fillFor, fillId, firstDayOfWeek, firstEnabledIndex, fmtSliderDate, formatDate, fromKey, glowId, groundId, groupColors, highlightOpacity, inputClasses, isSeverityTone, ladderScale, lastEnabledIndex, linearPath, linearScale, logScale, maskId, matchTypeahead, mediaFileName, monotonePath, nextEnabledIndex, niceMax, polygonPoints, popupBounds, radiusScale, resolvePortalBrandAsset, resolveSeriesColor, resolveTheme, selectionAt, seriesColor, severityOf, splinePath, squarify, stagger, stepPath, tabButtonId, tabPanelId, toDayMs, toISODate, toKey, useAppUpdate, useClickOutside, useDropdownPosition, useHighlight, usePlotWidth, usePortalBranding, useProductionTimeline, useTheme };
14106
+ //# sourceMappingURL=chunk-YA4EE7ST.js.map
14107
+ //# sourceMappingURL=chunk-YA4EE7ST.js.map