@octavius2929-personal/design-system 1.4.1 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1000,36 +1000,103 @@ var import_react17 = require("react");
1000
1000
  var import_react16 = require("react");
1001
1001
 
1002
1002
  // src/components/avatar/use-styles.css.ts
1003
+ var dot = "use-styles_dot__1mn1rmu8";
1004
+ var dotSize = { sm: "use-styles_dotSize_sm__1mn1rmu9", md: "use-styles_dotSize_md__1mn1rmua", lg: "use-styles_dotSize_lg__1mn1rmub" };
1005
+ var dotTone = { online: "use-styles_dotTone_online__1mn1rmuc", away: "use-styles_dotTone_away__1mn1rmud", busy: "use-styles_dotTone_busy__1mn1rmue", offline: "use-styles_dotTone_offline__1mn1rmuf" };
1006
+ var image = "use-styles_image__1mn1rmu2";
1007
+ var mark = "use-styles_mark__1mn1rmug";
1008
+ var markShape = { online: "use-styles_markShape_online__1mn1rmuh", busy: "use-styles_markShape_busy__1mn1rmui", away: "use-styles_markShape_away__1mn1rmuj", offline: "use-styles_markShape_offline__1mn1rmuk" };
1003
1009
  var root3 = "use-styles_root__1mn1rmu0";
1004
- var size2 = { sm: "use-styles_size_sm__1mn1rmu1", md: "use-styles_size_md__1mn1rmu2", lg: "use-styles_size_lg__1mn1rmu3" };
1005
- var variant = { "default": "use-styles_variant_default__1mn1rmu4", filled: "use-styles_variant_filled__1mn1rmu5" };
1010
+ var size2 = { sm: "use-styles_size_sm__1mn1rmu3", md: "use-styles_size_md__1mn1rmu4", lg: "use-styles_size_lg__1mn1rmu5" };
1011
+ var statusText = "surfaces_srOnly__1qa7atn0";
1012
+ var variant = { "default": "use-styles_variant_default__1mn1rmu6", filled: "use-styles_variant_filled__1mn1rmu7" };
1013
+ var visual = "use-styles_visual__1mn1rmu1";
1006
1014
 
1007
1015
  // src/components/avatar/use-styles.ts
1008
- function useStyles6({
1009
- size: size3 = "md",
1010
- filled,
1011
- className
1012
- }) {
1016
+ function useStyles6({ size: size3 = "md", filled, status, className }) {
1013
1017
  const { themeClass } = useTheme();
1014
1018
  const root25 = (0, import_react16.useMemo)(
1015
- () => [
1016
- themeClass,
1017
- root3,
1018
- size2[size3],
1019
- filled ? variant.filled : variant.default,
1020
- className
1021
- ].filter(Boolean).join(" "),
1022
- [themeClass, size3, filled, className]
1019
+ () => [themeClass, root3, size2[size3]].filter(Boolean).join(" "),
1020
+ [themeClass, size3]
1023
1021
  );
1024
- return { root: root25 };
1022
+ const visual2 = (0, import_react16.useMemo)(
1023
+ () => [visual, filled ? variant.filled : variant.default, className].filter(Boolean).join(" "),
1024
+ [filled, className]
1025
+ );
1026
+ const dot4 = (0, import_react16.useMemo)(
1027
+ () => status ? [dot, dotSize[size3], dotTone[status]].filter(Boolean).join(" ") : "",
1028
+ [status, size3]
1029
+ );
1030
+ const mark2 = (0, import_react16.useMemo)(
1031
+ () => status ? [mark, markShape[status]].filter(Boolean).join(" ") : "",
1032
+ [status]
1033
+ );
1034
+ return { root: root25, visual: visual2, image, dot: dot4, mark: mark2, statusText };
1025
1035
  }
1026
1036
 
1027
1037
  // src/components/avatar/index.tsx
1028
1038
  var import_jsx_runtime8 = require("react/jsx-runtime");
1029
- var Avatar = (0, import_react17.forwardRef)(function Avatar2({ size: size3, filled, className, children, testId, ...rest }, ref) {
1030
- const { root: root25 } = useStyles6({ size: size3, filled, className });
1031
- const { testId: dataTestId } = useTestId("media", testId);
1032
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { ref, className: root25, "data-testid": dataTestId, ...rest, children });
1039
+ function getInitials(name) {
1040
+ const words = name?.trim().split(/\s+/).filter(Boolean) ?? [];
1041
+ if (words.length === 0) return "";
1042
+ const firstWord = words[0] ?? "";
1043
+ const firstLetter = Array.from(firstWord)[0] ?? "";
1044
+ if (words.length === 1) return firstLetter.toLocaleUpperCase();
1045
+ const secondWord = words[1] ?? "";
1046
+ const secondLetter = Array.from(secondWord)[0] ?? "";
1047
+ return (firstLetter + secondLetter).toLocaleUpperCase();
1048
+ }
1049
+ var statusLabel = {
1050
+ online: "Online",
1051
+ away: "Away",
1052
+ busy: "Busy",
1053
+ offline: "Offline"
1054
+ };
1055
+ var Avatar = (0, import_react17.forwardRef)(function Avatar2({
1056
+ size: size3,
1057
+ filled,
1058
+ src,
1059
+ alt,
1060
+ name,
1061
+ status,
1062
+ decorative = false,
1063
+ className,
1064
+ children,
1065
+ testId,
1066
+ ...rest
1067
+ }, ref) {
1068
+ const [imgFailed, setImgFailed] = (0, import_react17.useState)(false);
1069
+ const [lastSrc, setLastSrc] = (0, import_react17.useState)(src);
1070
+ if (src !== lastSrc) {
1071
+ setLastSrc(src);
1072
+ setImgFailed(false);
1073
+ }
1074
+ const { root: root25, visual: visual2, image: image2, dot: dot4, mark: mark2, statusText: statusText2 } = useStyles6({
1075
+ size: size3,
1076
+ filled,
1077
+ status,
1078
+ className
1079
+ });
1080
+ const { testId: dataTestId, slot } = useTestId("media", testId);
1081
+ const showImage = Boolean(src) && !imgFailed;
1082
+ const accessibleName = alt?.trim() || name?.trim() || void 0;
1083
+ const fallback = children ?? getInitials(name);
1084
+ const visualA11yProps = decorative ? { "aria-hidden": true } : showImage ? {} : accessibleName ? { role: "img", "aria-label": accessibleName } : {};
1085
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { ref, className: root25, "data-testid": dataTestId, ...rest, children: [
1086
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: visual2, "data-testid": slot("visual"), ...visualA11yProps, children: showImage ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1087
+ "img",
1088
+ {
1089
+ src,
1090
+ alt: decorative ? "" : accessibleName ?? "",
1091
+ className: image2,
1092
+ onError: () => setImgFailed(true)
1093
+ }
1094
+ ) : fallback }),
1095
+ status && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: dot4, "data-testid": slot("status"), "data-status": status, children: [
1096
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: mark2, "aria-hidden": "true" }),
1097
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: statusText2, children: statusLabel[status] })
1098
+ ] })
1099
+ ] });
1033
1100
  });
1034
1101
 
1035
1102
  // src/components/badge/index.tsx
@@ -1039,7 +1106,7 @@ var import_react19 = require("react");
1039
1106
  var import_react18 = require("react");
1040
1107
 
1041
1108
  // src/components/badge/use-styles.css.ts
1042
- var dot = "use-styles_dot__1wpei6p1";
1109
+ var dot2 = "use-styles_dot__1wpei6p1";
1043
1110
  var root4 = "use-styles_root__1wpei6p0";
1044
1111
  var tone2 = { ink: "use-styles_tone_ink__1wpei6p2", accent: "use-styles_tone_accent__1wpei6p3" };
1045
1112
 
@@ -1053,18 +1120,18 @@ function useStyles7({
1053
1120
  () => [themeClass, root4, className].filter(Boolean).join(" "),
1054
1121
  [themeClass, className]
1055
1122
  );
1056
- const dot3 = (0, import_react18.useMemo)(() => [dot, tone2[tone4]].join(" "), [tone4]);
1057
- return { root: root25, dot: dot3 };
1123
+ const dot4 = (0, import_react18.useMemo)(() => [dot2, tone2[tone4]].join(" "), [tone4]);
1124
+ return { root: root25, dot: dot4 };
1058
1125
  }
1059
1126
 
1060
1127
  // src/components/badge/index.tsx
1061
1128
  var import_jsx_runtime9 = require("react/jsx-runtime");
1062
1129
  var Badge = (0, import_react19.forwardRef)(function Badge2({ count, tone: tone4, className, children, testId, ...rest }, ref) {
1063
- const { root: root25, dot: dot3 } = useStyles7({ tone: tone4, className });
1130
+ const { root: root25, dot: dot4 } = useStyles7({ tone: tone4, className });
1064
1131
  const { testId: dataTestId, slot } = useTestId("media", testId);
1065
1132
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { ref, className: root25, "data-testid": dataTestId, ...rest, children: [
1066
1133
  children,
1067
- count != null && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: dot3, "data-testid": slot("dot"), children: count })
1134
+ count != null && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: dot4, "data-testid": slot("dot"), children: count })
1068
1135
  ] });
1069
1136
  });
1070
1137
 
@@ -1331,7 +1398,7 @@ var import_react26 = require("react");
1331
1398
  // src/components/radio/use-styles.css.ts
1332
1399
  var circle = "use-styles_circle__vy61b42";
1333
1400
  var disabled2 = "use-styles_disabled__vy61b41";
1334
- var dot2 = "use-styles_dot__vy61b43";
1401
+ var dot3 = "use-styles_dot__vy61b43";
1335
1402
  var input2 = "surfaces_srOnly__1qa7atn0";
1336
1403
  var label2 = "use-styles_label__vy61b44";
1337
1404
  var root7 = "use-styles_root__vy61b40";
@@ -1350,7 +1417,7 @@ function useStyles11({
1350
1417
  root: root25,
1351
1418
  input: input2,
1352
1419
  circle,
1353
- dot: dot2,
1420
+ dot: dot3,
1354
1421
  label: label2
1355
1422
  };
1356
1423
  }
@@ -1358,7 +1425,7 @@ function useStyles11({
1358
1425
  // src/components/radio/index.tsx
1359
1426
  var import_jsx_runtime15 = require("react/jsx-runtime");
1360
1427
  var Radio = (0, import_react27.forwardRef)(function Radio2({ checked, onChange, label: label8, name, value, disabled: disabled4, testId, ...rest }, ref) {
1361
- const { root: root25, input: input6, circle: circle2, dot: dot3, label: labelClass } = useStyles11({ disabled: disabled4 });
1428
+ const { root: root25, input: input6, circle: circle2, dot: dot4, label: labelClass } = useStyles11({ disabled: disabled4 });
1362
1429
  const { testId: dataTestId } = useTestId("toggle", testId);
1363
1430
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: root25, "data-testid": dataTestId, "data-state": states({ checked, disabled: disabled4 }), children: [
1364
1431
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
@@ -1375,7 +1442,7 @@ var Radio = (0, import_react27.forwardRef)(function Radio2({ checked, onChange,
1375
1442
  ...rest
1376
1443
  }
1377
1444
  ),
1378
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: circle2, children: checked && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: dot3 }) }),
1445
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: circle2, children: checked && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: dot4 }) }),
1379
1446
  label8 != null && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: labelClass, children: label8 })
1380
1447
  ] });
1381
1448
  });
@@ -2191,41 +2258,123 @@ var Alert = (0, import_react43.forwardRef)(function Alert2({ severity: severity2
2191
2258
  });
2192
2259
 
2193
2260
  // src/components/tooltip/index.tsx
2194
- var import_react45 = require("react");
2261
+ var import_react46 = require("react");
2262
+ var import_react_dom = require("react-dom");
2195
2263
 
2196
- // src/components/tooltip/use-styles.ts
2264
+ // src/hooks/use-floating-position/index.ts
2197
2265
  var import_react44 = require("react");
2198
2266
 
2267
+ // src/hooks/use-floating-position/compute-position.ts
2268
+ function computeFloatingPosition({
2269
+ anchorRect,
2270
+ overlaySize,
2271
+ viewport,
2272
+ placement = "bottom",
2273
+ align: align2 = "center",
2274
+ offset = 4,
2275
+ margin = 8
2276
+ }) {
2277
+ const spaceBelow = viewport.height - anchorRect.bottom;
2278
+ const spaceAbove = anchorRect.top;
2279
+ const needed = overlaySize.height + offset;
2280
+ const fitsBelow = spaceBelow >= needed;
2281
+ const fitsAbove = spaceAbove >= needed;
2282
+ let resolvedPlacement = placement;
2283
+ if (placement === "bottom" && !fitsBelow && fitsAbove) {
2284
+ resolvedPlacement = "top";
2285
+ } else if (placement === "top" && !fitsAbove && fitsBelow) {
2286
+ resolvedPlacement = "bottom";
2287
+ }
2288
+ const top = resolvedPlacement === "bottom" ? anchorRect.bottom + offset : anchorRect.top - offset - overlaySize.height;
2289
+ let left;
2290
+ if (align2 === "start") {
2291
+ left = anchorRect.left;
2292
+ } else if (align2 === "end") {
2293
+ left = anchorRect.right - overlaySize.width;
2294
+ } else {
2295
+ left = anchorRect.left + anchorRect.width / 2 - overlaySize.width / 2;
2296
+ }
2297
+ const minLeft = margin;
2298
+ const maxLeft = viewport.width - overlaySize.width - margin;
2299
+ left = maxLeft < minLeft ? minLeft : Math.min(Math.max(left, minLeft), maxLeft);
2300
+ return { placement: resolvedPlacement, top, left };
2301
+ }
2302
+
2303
+ // src/hooks/use-floating-position/index.ts
2304
+ function useFloatingPosition(anchorRef, overlayRef, { open, placement, align: align2, offset, margin }) {
2305
+ (0, import_react44.useLayoutEffect)(() => {
2306
+ if (!open) return;
2307
+ const recalc = () => {
2308
+ const anchor = anchorRef.current;
2309
+ const overlay2 = overlayRef.current;
2310
+ if (!anchor || !overlay2) return;
2311
+ const next = computeFloatingPosition({
2312
+ anchorRect: anchor.getBoundingClientRect(),
2313
+ overlaySize: { width: overlay2.offsetWidth, height: overlay2.offsetHeight },
2314
+ viewport: { width: document.documentElement.clientWidth, height: window.innerHeight },
2315
+ placement,
2316
+ align: align2,
2317
+ offset,
2318
+ margin
2319
+ });
2320
+ overlay2.style.top = `${next.top}px`;
2321
+ overlay2.style.left = `${next.left}px`;
2322
+ overlay2.style.visibility = "visible";
2323
+ };
2324
+ recalc();
2325
+ window.addEventListener("scroll", recalc, true);
2326
+ window.addEventListener("resize", recalc);
2327
+ return () => {
2328
+ window.removeEventListener("scroll", recalc, true);
2329
+ window.removeEventListener("resize", recalc);
2330
+ };
2331
+ }, [open, placement, align2, offset, margin, anchorRef, overlayRef]);
2332
+ }
2333
+
2334
+ // src/components/tooltip/use-styles.ts
2335
+ var import_react45 = require("react");
2336
+
2199
2337
  // src/components/tooltip/use-styles.css.ts
2200
2338
  var bubble = "use-styles_bubble__h9kvh1 surfaces_inkySurface__1qa7atn2";
2201
- var placement = { top: "use-styles_placement_top__h9kvh2", bottom: "use-styles_placement_bottom__h9kvh3" };
2202
2339
  var wrapper = "use-styles_wrapper__h9kvh0";
2203
2340
 
2204
2341
  // src/components/tooltip/use-styles.ts
2205
- function useStyles19({
2206
- placement: placement2 = "top"
2207
- }) {
2342
+ function useStyles19() {
2208
2343
  const { themeClass } = useTheme();
2209
- const wrapper4 = (0, import_react44.useMemo)(
2344
+ const wrapper4 = (0, import_react45.useMemo)(
2210
2345
  () => [themeClass, wrapper].filter(Boolean).join(" "),
2211
2346
  [themeClass]
2212
2347
  );
2213
- const bubble2 = (0, import_react44.useMemo)(
2214
- () => [bubble, placement[placement2]].filter(Boolean).join(" "),
2215
- [placement2]
2216
- );
2348
+ const bubble2 = (0, import_react45.useMemo)(() => [themeClass, bubble].filter(Boolean).join(" "), [themeClass]);
2217
2349
  return { wrapper: wrapper4, bubble: bubble2 };
2218
2350
  }
2219
2351
 
2220
2352
  // src/components/tooltip/index.tsx
2221
2353
  var import_jsx_runtime31 = require("react/jsx-runtime");
2222
2354
  var HIDE_DELAY = 120;
2223
- var Tooltip = (0, import_react45.forwardRef)(function Tooltip2({ label: label8, children, placement: placement2, testId }, ref) {
2224
- const [open, setOpen] = (0, import_react45.useState)(false);
2225
- const tooltipId = (0, import_react45.useId)();
2226
- const { wrapper: wrapper4, bubble: bubble2 } = useStyles19({ placement: placement2 });
2355
+ var GAP = 4;
2356
+ function assignRef(ref, value) {
2357
+ if (typeof ref === "function") ref(value);
2358
+ else if (ref) ref.current = value;
2359
+ }
2360
+ var Tooltip = (0, import_react46.forwardRef)(function Tooltip2({ label: label8, children, placement = "top", testId }, ref) {
2361
+ const [open, setOpen] = (0, import_react46.useState)(false);
2362
+ const tooltipId = (0, import_react46.useId)();
2363
+ const { wrapper: wrapper4, bubble: bubble2 } = useStyles19();
2227
2364
  const { testId: dataTestId, slot } = useTestId("feedback", testId);
2228
- const hideTimer = (0, import_react45.useRef)(null);
2365
+ const hideTimer = (0, import_react46.useRef)(null);
2366
+ const wrapperRef = (0, import_react46.useRef)(null);
2367
+ const setWrapperRef = (node) => {
2368
+ wrapperRef.current = node;
2369
+ assignRef(ref, node);
2370
+ };
2371
+ const bubbleRef = (0, import_react46.useRef)(null);
2372
+ useFloatingPosition(wrapperRef, bubbleRef, {
2373
+ open,
2374
+ placement,
2375
+ align: "center",
2376
+ offset: GAP
2377
+ });
2229
2378
  const clearHide = () => {
2230
2379
  if (hideTimer.current) {
2231
2380
  clearTimeout(hideTimer.current);
@@ -2244,7 +2393,7 @@ var Tooltip = (0, import_react45.forwardRef)(function Tooltip2({ label: label8,
2244
2393
  clearHide();
2245
2394
  setOpen(false);
2246
2395
  };
2247
- (0, import_react45.useEffect)(() => {
2396
+ (0, import_react46.useEffect)(() => {
2248
2397
  return () => {
2249
2398
  if (hideTimer.current) clearTimeout(hideTimer.current);
2250
2399
  };
@@ -2257,11 +2406,11 @@ var Tooltip = (0, import_react45.forwardRef)(function Tooltip2({ label: label8,
2257
2406
  };
2258
2407
  const previousDescribedBy = children.props["aria-describedby"];
2259
2408
  const describedBy = open ? [previousDescribedBy, tooltipId].filter(Boolean).join(" ") : previousDescribedBy;
2260
- const trigger2 = (0, import_react45.cloneElement)(children, { "aria-describedby": describedBy });
2409
+ const trigger2 = (0, import_react46.cloneElement)(children, { "aria-describedby": describedBy });
2261
2410
  return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
2262
2411
  "span",
2263
2412
  {
2264
- ref,
2413
+ ref: setWrapperRef,
2265
2414
  className: wrapper4,
2266
2415
  "data-testid": dataTestId,
2267
2416
  onMouseEnter: show,
@@ -2271,25 +2420,29 @@ var Tooltip = (0, import_react45.forwardRef)(function Tooltip2({ label: label8,
2271
2420
  onKeyDown: handleKeyDown,
2272
2421
  children: [
2273
2422
  trigger2,
2274
- open && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
2275
- "span",
2276
- {
2277
- id: tooltipId,
2278
- role: "tooltip",
2279
- className: bubble2,
2280
- "data-testid": slot("bubble"),
2281
- onMouseEnter: show,
2282
- onMouseLeave: scheduleHide,
2283
- children: label8
2284
- }
2285
- )
2423
+ open && typeof document !== "undefined" ? (0, import_react_dom.createPortal)(
2424
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
2425
+ "span",
2426
+ {
2427
+ ref: bubbleRef,
2428
+ id: tooltipId,
2429
+ role: "tooltip",
2430
+ className: bubble2,
2431
+ "data-testid": slot("bubble"),
2432
+ onMouseEnter: show,
2433
+ onMouseLeave: scheduleHide,
2434
+ children: label8
2435
+ }
2436
+ ),
2437
+ document.body
2438
+ ) : null
2286
2439
  ]
2287
2440
  }
2288
2441
  );
2289
2442
  });
2290
2443
 
2291
2444
  // src/components/select/index.tsx
2292
- var import_react47 = require("react");
2445
+ var import_react48 = require("react");
2293
2446
 
2294
2447
  // src/components/icons/chevron-down/index.tsx
2295
2448
  var import_jsx_runtime32 = require("react/jsx-runtime");
@@ -2314,7 +2467,7 @@ function ChevronDownIcon({ size: size3 = 20, strokeWidth = 1.75, title, ...rest
2314
2467
  }
2315
2468
 
2316
2469
  // src/components/select/use-styles.ts
2317
- var import_react46 = require("react");
2470
+ var import_react47 = require("react");
2318
2471
 
2319
2472
  // src/components/select/use-styles.css.ts
2320
2473
  var chevron = "use-styles_chevron__1w1czpb4";
@@ -2333,7 +2486,7 @@ function useStyles20({
2333
2486
  open = false
2334
2487
  }) {
2335
2488
  const { themeClass } = useTheme();
2336
- return (0, import_react46.useMemo)(() => {
2489
+ return (0, import_react47.useMemo)(() => {
2337
2490
  const chevron3 = [chevron, open && chevronOpen].filter(Boolean).join(" ");
2338
2491
  return {
2339
2492
  root: [themeClass, root14].filter(Boolean).join(" "),
@@ -2349,7 +2502,7 @@ function useStyles20({
2349
2502
 
2350
2503
  // src/components/select/index.tsx
2351
2504
  var import_jsx_runtime33 = require("react/jsx-runtime");
2352
- var Select = (0, import_react47.forwardRef)(function Select2({
2505
+ var Select = (0, import_react48.forwardRef)(function Select2({
2353
2506
  options,
2354
2507
  value,
2355
2508
  onChange,
@@ -2360,15 +2513,15 @@ var Select = (0, import_react47.forwardRef)(function Select2({
2360
2513
  "aria-labelledby": ariaLabelledBy,
2361
2514
  ...rest
2362
2515
  }, ref) {
2363
- const [open, setOpen] = (0, import_react47.useState)(false);
2364
- const [activeIndex, setActiveIndex] = (0, import_react47.useState)(0);
2365
- const rootRef = (0, import_react47.useRef)(null);
2516
+ const [open, setOpen] = (0, import_react48.useState)(false);
2517
+ const [activeIndex, setActiveIndex] = (0, import_react48.useState)(0);
2518
+ const rootRef = (0, import_react48.useRef)(null);
2366
2519
  const setRootRef = (node) => {
2367
2520
  rootRef.current = node;
2368
2521
  if (typeof ref === "function") ref(node);
2369
2522
  else if (ref) ref.current = node;
2370
2523
  };
2371
- const baseId = (0, import_react47.useId)();
2524
+ const baseId = (0, import_react48.useId)();
2372
2525
  const labelId = `${baseId}-label`;
2373
2526
  const optionId = (index) => `${baseId}-option-${index}`;
2374
2527
  const triggerLabelledBy = [label8 ? labelId : null, ariaLabelledBy].filter(Boolean).join(" ") || void 0;
@@ -2381,7 +2534,7 @@ var Select = (0, import_react47.forwardRef)(function Select2({
2381
2534
  menu: menu2,
2382
2535
  optionClass
2383
2536
  } = useStyles20({ open });
2384
- (0, import_react47.useEffect)(() => {
2537
+ (0, import_react48.useEffect)(() => {
2385
2538
  if (!open) return;
2386
2539
  const onPointerDown = (event) => {
2387
2540
  if (rootRef.current && !rootRef.current.contains(event.target)) {
@@ -2493,10 +2646,10 @@ var Select = (0, import_react47.forwardRef)(function Select2({
2493
2646
  });
2494
2647
 
2495
2648
  // src/components/slider/index.tsx
2496
- var import_react49 = require("react");
2649
+ var import_react50 = require("react");
2497
2650
 
2498
2651
  // src/components/slider/use-styles.ts
2499
- var import_react48 = require("react");
2652
+ var import_react49 = require("react");
2500
2653
 
2501
2654
  // src/components/slider/use-styles.css.ts
2502
2655
  var input5 = "use-styles_input__okw59n3";
@@ -2510,7 +2663,7 @@ var wrapper2 = "use-styles_wrapper__okw59n6";
2510
2663
  // src/components/slider/use-styles.ts
2511
2664
  function useStyles21() {
2512
2665
  const { themeClass } = useTheme();
2513
- return (0, import_react48.useMemo)(() => {
2666
+ return (0, import_react49.useMemo)(() => {
2514
2667
  const root25 = [themeClass, root15].filter(Boolean).join(" ");
2515
2668
  return {
2516
2669
  wrapper: wrapper2,
@@ -2526,7 +2679,7 @@ function useStyles21() {
2526
2679
 
2527
2680
  // src/components/slider/index.tsx
2528
2681
  var import_jsx_runtime34 = require("react/jsx-runtime");
2529
- var Slider = (0, import_react49.forwardRef)(function Slider2({ value = 0, onChange, min = 0, max = 100, step: step2 = 1, disabled: disabled4, label: label8, ...rest }, ref) {
2682
+ var Slider = (0, import_react50.forwardRef)(function Slider2({ value = 0, onChange, min = 0, max = 100, step: step2 = 1, disabled: disabled4, label: label8, ...rest }, ref) {
2530
2683
  const { wrapper: wrapper4, label: labelClass, root: root25, track: track4, range: range2, thumb: thumb2, input: input6 } = useStyles21();
2531
2684
  const span = max - min;
2532
2685
  const percent = span > 0 ? (value - min) / span * 100 : 0;
@@ -2560,10 +2713,10 @@ var Slider = (0, import_react49.forwardRef)(function Slider2({ value = 0, onChan
2560
2713
  });
2561
2714
 
2562
2715
  // src/components/accordion/index.tsx
2563
- var import_react51 = require("react");
2716
+ var import_react52 = require("react");
2564
2717
 
2565
2718
  // src/components/accordion/use-styles.ts
2566
- var import_react50 = require("react");
2719
+ var import_react51 = require("react");
2567
2720
 
2568
2721
  // src/components/accordion/use-styles.css.ts
2569
2722
  var chevron2 = "use-styles_chevron__1cjrdh93";
@@ -2576,7 +2729,7 @@ var root16 = "use-styles_root__1cjrdh90";
2576
2729
  // src/components/accordion/use-styles.ts
2577
2730
  function useStyles22({ className }) {
2578
2731
  const { themeClass } = useTheme();
2579
- return (0, import_react50.useMemo)(
2732
+ return (0, import_react51.useMemo)(
2580
2733
  () => ({
2581
2734
  root: [themeClass, root16, className].filter(Boolean).join(" "),
2582
2735
  item,
@@ -2590,8 +2743,8 @@ function useStyles22({ className }) {
2590
2743
 
2591
2744
  // src/components/accordion/index.tsx
2592
2745
  var import_jsx_runtime35 = require("react/jsx-runtime");
2593
- var Accordion = (0, import_react51.forwardRef)(function Accordion2({ items, multiple = false, defaultOpen = [], className, testId }, ref) {
2594
- const [open, setOpen] = (0, import_react51.useState)(defaultOpen);
2746
+ var Accordion = (0, import_react52.forwardRef)(function Accordion2({ items, multiple = false, defaultOpen = [], className, testId }, ref) {
2747
+ const [open, setOpen] = (0, import_react52.useState)(defaultOpen);
2595
2748
  const { root: root25, item: item3, header: header3, chevronFor, panel: panel3 } = useStyles22({ className });
2596
2749
  const { testId: dataTestId, slot } = useTestId("layout", testId);
2597
2750
  const toggle = (id) => {
@@ -2648,7 +2801,7 @@ var Accordion = (0, import_react51.forwardRef)(function Accordion2({ items, mult
2648
2801
  });
2649
2802
 
2650
2803
  // src/components/breadcrumbs/index.tsx
2651
- var import_react53 = require("react");
2804
+ var import_react54 = require("react");
2652
2805
 
2653
2806
  // src/components/icons/chevron-right/index.tsx
2654
2807
  var import_jsx_runtime36 = require("react/jsx-runtime");
@@ -2673,7 +2826,7 @@ function ChevronRightIcon({ size: size3 = 20, strokeWidth = 1.75, title, ...rest
2673
2826
  }
2674
2827
 
2675
2828
  // src/components/breadcrumbs/use-styles.ts
2676
- var import_react52 = require("react");
2829
+ var import_react53 = require("react");
2677
2830
 
2678
2831
  // src/components/breadcrumbs/use-styles.css.ts
2679
2832
  var crumb = "use-styles_crumb__7u0du61";
@@ -2684,7 +2837,7 @@ var separator = "use-styles_separator__7u0du63";
2684
2837
  // src/components/breadcrumbs/use-styles.ts
2685
2838
  function useStyles23({ className }) {
2686
2839
  const { themeClass } = useTheme();
2687
- const root25 = (0, import_react52.useMemo)(
2840
+ const root25 = (0, import_react53.useMemo)(
2688
2841
  () => [themeClass, root17, className].filter(Boolean).join(" "),
2689
2842
  [themeClass, className]
2690
2843
  );
@@ -2693,13 +2846,13 @@ function useStyles23({ className }) {
2693
2846
 
2694
2847
  // src/components/breadcrumbs/index.tsx
2695
2848
  var import_jsx_runtime37 = require("react/jsx-runtime");
2696
- var Breadcrumbs = (0, import_react53.forwardRef)(function Breadcrumbs2({ items, className, testId, ...rest }, ref) {
2849
+ var Breadcrumbs = (0, import_react54.forwardRef)(function Breadcrumbs2({ items, className, testId, ...rest }, ref) {
2697
2850
  const { root: root25, crumb: crumb2, current: current2, separator: separator2 } = useStyles23({ className });
2698
2851
  const { testId: dataTestId, slot } = useTestId("nav", testId);
2699
2852
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("nav", { ref, "aria-label": "Breadcrumb", className: root25, "data-testid": dataTestId, ...rest, children: items.map((item3, index) => {
2700
2853
  const isLast = index === items.length - 1;
2701
2854
  const key = index;
2702
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_react53.Fragment, { children: [
2855
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_react54.Fragment, { children: [
2703
2856
  isLast ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: current2, "aria-current": "page", "data-testid": slot(`crumb-${index}`), children: item3.label }) : item3.href ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("a", { className: crumb2, href: item3.href, "data-testid": slot(`crumb-${index}`), children: item3.label }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: crumb2, "data-testid": slot(`crumb-${index}`), children: item3.label }),
2704
2857
  !isLast && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: separator2, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ChevronRightIcon, { size: 14 }) })
2705
2858
  ] }, key);
@@ -2707,7 +2860,7 @@ var Breadcrumbs = (0, import_react53.forwardRef)(function Breadcrumbs2({ items,
2707
2860
  });
2708
2861
 
2709
2862
  // src/components/pagination/index.tsx
2710
- var import_react55 = require("react");
2863
+ var import_react56 = require("react");
2711
2864
 
2712
2865
  // src/components/icons/chevron-left/index.tsx
2713
2866
  var import_jsx_runtime38 = require("react/jsx-runtime");
@@ -2732,7 +2885,7 @@ function ChevronLeftIcon({ size: size3 = 20, strokeWidth = 1.75, title, ...rest
2732
2885
  }
2733
2886
 
2734
2887
  // src/components/pagination/use-styles.ts
2735
- var import_react54 = require("react");
2888
+ var import_react55 = require("react");
2736
2889
 
2737
2890
  // src/components/pagination/use-styles.css.ts
2738
2891
  var ellipsis = "use-styles_ellipsis__1azgzoh3";
@@ -2744,7 +2897,7 @@ var root18 = "use-styles_root__1azgzoh0";
2744
2897
  // src/components/pagination/use-styles.ts
2745
2898
  function useStyles24() {
2746
2899
  const { themeClass } = useTheme();
2747
- return (0, import_react54.useMemo)(
2900
+ return (0, import_react55.useMemo)(
2748
2901
  () => ({
2749
2902
  root: [themeClass, root18].filter(Boolean).join(" "),
2750
2903
  pageBtnFor: (active2) => [pageBtn, active2 && pageActive].filter(Boolean).join(" "),
@@ -2770,7 +2923,7 @@ function buildItems(count, page, siblingCount) {
2770
2923
  if (last > first) items.push(last);
2771
2924
  return items;
2772
2925
  }
2773
- var Pagination = (0, import_react55.forwardRef)(function Pagination2({ count, page = 1, onChange, siblingCount = 1, testId, ...rest }, ref) {
2926
+ var Pagination = (0, import_react56.forwardRef)(function Pagination2({ count, page = 1, onChange, siblingCount = 1, testId, ...rest }, ref) {
2774
2927
  const { root: root25, pageBtnFor, ellipsis: ellipsis2, nav: nav2 } = useStyles24();
2775
2928
  const { testId: dataTestId, slot } = useTestId("nav", testId);
2776
2929
  const total = Math.max(1, count);
@@ -2828,10 +2981,10 @@ var Pagination = (0, import_react55.forwardRef)(function Pagination2({ count, pa
2828
2981
  });
2829
2982
 
2830
2983
  // src/components/stepper/index.tsx
2831
- var import_react57 = require("react");
2984
+ var import_react58 = require("react");
2832
2985
 
2833
2986
  // src/components/stepper/use-styles.ts
2834
- var import_react56 = require("react");
2987
+ var import_react57 = require("react");
2835
2988
 
2836
2989
  // src/components/stepper/use-styles.css.ts
2837
2990
  var connector = "use-styles_connector__79pt4e7";
@@ -2846,7 +2999,7 @@ var step = "use-styles_step__79pt4e1";
2846
2999
  // src/components/stepper/use-styles.ts
2847
3000
  function useStyles25({ className }) {
2848
3001
  const { themeClass } = useTheme();
2849
- return (0, import_react56.useMemo)(() => {
3002
+ return (0, import_react57.useMemo)(() => {
2850
3003
  const root25 = [themeClass, root19, className].filter(Boolean).join(" ");
2851
3004
  const markerFor = (state) => [
2852
3005
  marker,
@@ -2860,7 +3013,7 @@ function useStyles25({ className }) {
2860
3013
 
2861
3014
  // src/components/stepper/index.tsx
2862
3015
  var import_jsx_runtime40 = require("react/jsx-runtime");
2863
- var Stepper = (0, import_react57.forwardRef)(function Stepper2({ steps, active: active2 = 0, className, testId, ...rest }, ref) {
3016
+ var Stepper = (0, import_react58.forwardRef)(function Stepper2({ steps, active: active2 = 0, className, testId, ...rest }, ref) {
2864
3017
  const { root: root25, step: step2, connector: connector2, markerFor, labelFor } = useStyles25({ className });
2865
3018
  const { testId: dataTestId, slot } = useTestId("nav", testId);
2866
3019
  return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { ref, className: root25, "data-testid": dataTestId, ...rest, children: steps.map((s, index) => {
@@ -2868,7 +3021,7 @@ var Stepper = (0, import_react57.forwardRef)(function Stepper2({ steps, active:
2868
3021
  const isActive = state === "active";
2869
3022
  return (
2870
3023
  // biome-ignore lint/suspicious/noArrayIndexKey: steps are a static, ordered list with no stable id.
2871
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react57.Fragment, { children: [
3024
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react58.Fragment, { children: [
2872
3025
  /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
2873
3026
  "div",
2874
3027
  {
@@ -2889,10 +3042,10 @@ var Stepper = (0, import_react57.forwardRef)(function Stepper2({ steps, active:
2889
3042
  });
2890
3043
 
2891
3044
  // src/components/tabs/index.tsx
2892
- var import_react59 = require("react");
3045
+ var import_react60 = require("react");
2893
3046
 
2894
3047
  // src/components/tabs/use-styles.ts
2895
- var import_react58 = require("react");
3048
+ var import_react59 = require("react");
2896
3049
 
2897
3050
  // src/components/tabs/use-styles.css.ts
2898
3051
  var panel2 = "use-styles_panel__1l4m7t43";
@@ -2903,7 +3056,7 @@ var tabActive = "use-styles_tabActive__1l4m7t42";
2903
3056
  // src/components/tabs/use-styles.ts
2904
3057
  function useStyles26() {
2905
3058
  const { themeClass } = useTheme();
2906
- return (0, import_react58.useMemo)(() => {
3059
+ return (0, import_react59.useMemo)(() => {
2907
3060
  const root25 = [themeClass, root20].filter(Boolean).join(" ");
2908
3061
  const tabClass = (active2) => [tab, active2 && tabActive].filter(Boolean).join(" ");
2909
3062
  return { root: root25, tab, tabClass, panel: panel2 };
@@ -2913,11 +3066,11 @@ function useStyles26() {
2913
3066
  // src/components/tabs/index.tsx
2914
3067
  var import_jsx_runtime41 = require("react/jsx-runtime");
2915
3068
  var ICON_SIZE3 = 16;
2916
- var Tabs = (0, import_react59.forwardRef)(function Tabs2({ items, value, onChange, testId, ...rest }, ref) {
3069
+ var Tabs = (0, import_react60.forwardRef)(function Tabs2({ items, value, onChange, testId, ...rest }, ref) {
2917
3070
  const { root: root25, tabClass, panel: panel3 } = useStyles26();
2918
3071
  const { testId: dataTestId, slot } = useTestId("nav", testId);
2919
- const baseId = (0, import_react59.useId)();
2920
- const tabRefs = (0, import_react59.useRef)([]);
3072
+ const baseId = (0, import_react60.useId)();
3073
+ const tabRefs = (0, import_react60.useRef)([]);
2921
3074
  const hasPanels = items.some((item3) => item3.content !== void 0);
2922
3075
  const activeIndex = items.findIndex((item3) => item3.value === value);
2923
3076
  const tabId = (v) => `${baseId}-tab-${v}`;
@@ -2997,10 +3150,11 @@ var Tabs = (0, import_react59.forwardRef)(function Tabs2({ items, value, onChang
2997
3150
  });
2998
3151
 
2999
3152
  // src/components/menu/index.tsx
3000
- var import_react61 = require("react");
3153
+ var import_react62 = require("react");
3154
+ var import_react_dom2 = require("react-dom");
3001
3155
 
3002
3156
  // src/components/menu/use-styles.ts
3003
- var import_react60 = require("react");
3157
+ var import_react61 = require("react");
3004
3158
 
3005
3159
  // src/components/menu/use-styles.css.ts
3006
3160
  var danger = "use-styles_danger__1uyxaj3";
@@ -3011,10 +3165,10 @@ var wrapper3 = "use-styles_wrapper__1uyxaj0";
3011
3165
  // src/components/menu/use-styles.ts
3012
3166
  function useStyles27() {
3013
3167
  const { themeClass } = useTheme();
3014
- return (0, import_react60.useMemo)(
3168
+ return (0, import_react61.useMemo)(
3015
3169
  () => ({
3016
3170
  wrapper: [themeClass, wrapper3].filter(Boolean).join(" "),
3017
- list: list2,
3171
+ list: [themeClass, list2].filter(Boolean).join(" "),
3018
3172
  item: item2,
3019
3173
  dangerItem: [item2, danger].join(" ")
3020
3174
  }),
@@ -3025,23 +3179,38 @@ function useStyles27() {
3025
3179
  // src/components/menu/index.tsx
3026
3180
  var import_jsx_runtime42 = require("react/jsx-runtime");
3027
3181
  var ICON_SIZE4 = 16;
3028
- function assignRef(ref, value) {
3182
+ var GAP2 = 4;
3183
+ var TYPEAHEAD_RESET_MS = 500;
3184
+ function assignRef2(ref, value) {
3029
3185
  if (typeof ref === "function") ref(value);
3030
3186
  else if (ref) ref.current = value;
3031
3187
  }
3032
- var Menu = (0, import_react61.forwardRef)(function Menu2({ trigger: trigger2, items, testId }, ref) {
3188
+ var Menu = (0, import_react62.forwardRef)(function Menu2({ trigger: trigger2, items, testId }, ref) {
3033
3189
  const { wrapper: wrapper4, list: list3, item: item3, dangerItem } = useStyles27();
3034
3190
  const { testId: rootTestId, slot } = useTestId("menu", testId);
3035
- const [open, setOpen] = (0, import_react61.useState)(false);
3036
- const [alignEnd, setAlignEnd] = (0, import_react61.useState)(false);
3037
- const rootRef = (0, import_react61.useRef)(null);
3191
+ const [open, setOpen] = (0, import_react62.useState)(false);
3192
+ const rootRef = (0, import_react62.useRef)(null);
3038
3193
  const setRootRef = (node) => {
3039
3194
  rootRef.current = node;
3040
- assignRef(ref, node);
3195
+ assignRef2(ref, node);
3041
3196
  };
3042
- const listRef = (0, import_react61.useRef)(null);
3043
- const triggerRef = (0, import_react61.useRef)(null);
3044
- const getMenuItems = () => Array.from(listRef.current?.querySelectorAll('[role="menuitem"]') ?? []);
3197
+ const listRef = (0, import_react62.useRef)(null);
3198
+ const triggerRef = (0, import_react62.useRef)(null);
3199
+ const pendingFocusRef = (0, import_react62.useRef)("first");
3200
+ const typeAheadRef = (0, import_react62.useRef)({
3201
+ query: "",
3202
+ timeout: null
3203
+ });
3204
+ useFloatingPosition(rootRef, listRef, {
3205
+ open,
3206
+ placement: "bottom",
3207
+ align: "start",
3208
+ offset: GAP2
3209
+ });
3210
+ const getMenuItems = (0, import_react62.useCallback)(
3211
+ () => Array.from(listRef.current?.querySelectorAll('[role="menuitem"]') ?? []),
3212
+ []
3213
+ );
3045
3214
  const focusItemAt = (index) => {
3046
3215
  const menuItems = getMenuItems();
3047
3216
  if (menuItems.length === 0) return;
@@ -3052,23 +3221,41 @@ var Menu = (0, import_react61.forwardRef)(function Menu2({ trigger: trigger2, it
3052
3221
  setOpen(false);
3053
3222
  triggerRef.current?.focus();
3054
3223
  };
3055
- (0, import_react61.useLayoutEffect)(() => {
3056
- if (!open) {
3057
- setAlignEnd(false);
3058
- return;
3224
+ const resetTypeAhead = (0, import_react62.useCallback)(() => {
3225
+ if (typeAheadRef.current.timeout) clearTimeout(typeAheadRef.current.timeout);
3226
+ typeAheadRef.current = { query: "", timeout: null };
3227
+ }, []);
3228
+ const handleTypeAhead = (key) => {
3229
+ if (typeAheadRef.current.timeout) clearTimeout(typeAheadRef.current.timeout);
3230
+ const query = typeAheadRef.current.query + key.toLowerCase();
3231
+ typeAheadRef.current.query = query;
3232
+ typeAheadRef.current.timeout = setTimeout(() => {
3233
+ typeAheadRef.current = { query: "", timeout: null };
3234
+ }, TYPEAHEAD_RESET_MS);
3235
+ const menuItems = getMenuItems();
3236
+ if (menuItems.length === 0) return;
3237
+ const current2 = menuItems.indexOf(document.activeElement);
3238
+ const startIndex = current2 === -1 ? 0 : current2 + 1;
3239
+ for (let i = 0; i < menuItems.length; i++) {
3240
+ const candidate = menuItems[(startIndex + i) % menuItems.length];
3241
+ const text2 = candidate?.textContent?.trim().toLowerCase() ?? "";
3242
+ if (text2.startsWith(query)) {
3243
+ candidate?.focus();
3244
+ return;
3245
+ }
3059
3246
  }
3060
- const listEl = listRef.current;
3061
- const rootEl = rootRef.current;
3062
- if (!listEl || !rootEl) return;
3063
- const rootLeft = rootEl.getBoundingClientRect().left;
3064
- const viewport = document.documentElement.clientWidth;
3065
- setAlignEnd(rootLeft + listEl.offsetWidth > viewport);
3066
- }, [open]);
3067
- (0, import_react61.useEffect)(() => {
3247
+ };
3248
+ (0, import_react62.useEffect)(() => {
3068
3249
  if (!open) return;
3069
- listRef.current?.querySelector('[role="menuitem"]')?.focus();
3250
+ const menuItems = getMenuItems();
3251
+ const index = pendingFocusRef.current === "last" ? menuItems.length - 1 : 0;
3252
+ menuItems[index]?.focus();
3253
+ pendingFocusRef.current = "first";
3070
3254
  const onDocMouseDown = (event) => {
3071
- if (rootRef.current && !rootRef.current.contains(event.target)) {
3255
+ const target = event.target;
3256
+ const insideTrigger = rootRef.current?.contains(target) ?? false;
3257
+ const insideList = listRef.current?.contains(target) ?? false;
3258
+ if (!insideTrigger && !insideList) {
3072
3259
  setOpen(false);
3073
3260
  }
3074
3261
  };
@@ -3083,8 +3270,9 @@ var Menu = (0, import_react61.forwardRef)(function Menu2({ trigger: trigger2, it
3083
3270
  return () => {
3084
3271
  document.removeEventListener("mousedown", onDocMouseDown);
3085
3272
  document.removeEventListener("keydown", onKeyDown);
3273
+ resetTypeAhead();
3086
3274
  };
3087
- }, [open]);
3275
+ }, [open, getMenuItems, resetTypeAhead]);
3088
3276
  const onMenuKeyDown = (event) => {
3089
3277
  const menuItems = getMenuItems();
3090
3278
  const current2 = menuItems.indexOf(document.activeElement);
@@ -3112,22 +3300,58 @@ var Menu = (0, import_react61.forwardRef)(function Menu2({ trigger: trigger2, it
3112
3300
  case "Tab":
3113
3301
  setOpen(false);
3114
3302
  break;
3303
+ case " ":
3304
+ event.preventDefault();
3305
+ if (typeAheadRef.current.query.length > 0) {
3306
+ handleTypeAhead(event.key);
3307
+ } else {
3308
+ menuItems[current2]?.click();
3309
+ }
3310
+ break;
3311
+ default:
3312
+ if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
3313
+ event.preventDefault();
3314
+ handleTypeAhead(event.key);
3315
+ }
3316
+ break;
3115
3317
  }
3116
3318
  };
3117
3319
  const triggerProps = trigger2.props;
3118
3320
  const consumerRef = trigger2.ref;
3119
3321
  const mergedTriggerRef = (node) => {
3120
3322
  triggerRef.current = node;
3121
- assignRef(consumerRef, node);
3323
+ assignRef2(consumerRef, node);
3122
3324
  };
3123
- const clonedTrigger = (0, import_react61.cloneElement)(trigger2, {
3325
+ const handleTriggerKeyDown = (event) => {
3326
+ triggerProps.onKeyDown?.(event);
3327
+ if (open) return;
3328
+ switch (event.key) {
3329
+ case "Enter":
3330
+ case " ":
3331
+ case "ArrowDown":
3332
+ event.preventDefault();
3333
+ pendingFocusRef.current = "first";
3334
+ setOpen(true);
3335
+ break;
3336
+ case "ArrowUp":
3337
+ event.preventDefault();
3338
+ pendingFocusRef.current = "last";
3339
+ setOpen(true);
3340
+ break;
3341
+ }
3342
+ };
3343
+ const clonedTrigger = (0, import_react62.cloneElement)(trigger2, {
3124
3344
  ref: mergedTriggerRef,
3125
3345
  "aria-haspopup": "menu",
3126
3346
  "aria-expanded": open,
3127
3347
  onClick: (event) => {
3128
3348
  triggerProps.onClick?.(event);
3129
- setOpen((prev) => !prev);
3130
- }
3349
+ setOpen((prev) => {
3350
+ if (!prev) pendingFocusRef.current = "first";
3351
+ return !prev;
3352
+ });
3353
+ },
3354
+ onKeyDown: handleTriggerKeyDown
3131
3355
  });
3132
3356
  return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
3133
3357
  "div",
@@ -3138,50 +3362,52 @@ var Menu = (0, import_react61.forwardRef)(function Menu2({ trigger: trigger2, it
3138
3362
  "data-state": open ? "open" : "closed",
3139
3363
  children: [
3140
3364
  clonedTrigger,
3141
- open && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
3142
- "div",
3143
- {
3144
- ref: listRef,
3145
- role: "menu",
3146
- className: list3,
3147
- "data-align": alignEnd ? "end" : "start",
3148
- "data-testid": slot("list"),
3149
- onKeyDown: onMenuKeyDown,
3150
- children: items.map((entry, index) => {
3151
- const ItemIcon = entry.icon;
3152
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
3153
- "button",
3154
- {
3155
- type: "button",
3156
- role: "menuitem",
3157
- tabIndex: -1,
3158
- className: entry.danger ? dangerItem : item3,
3159
- "data-testid": slot(`item-${index}`),
3160
- onClick: () => {
3161
- entry.onClick?.();
3162
- setOpen(false);
3365
+ open && typeof document !== "undefined" ? (0, import_react_dom2.createPortal)(
3366
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
3367
+ "div",
3368
+ {
3369
+ ref: listRef,
3370
+ role: "menu",
3371
+ className: list3,
3372
+ "data-testid": slot("list"),
3373
+ onKeyDown: onMenuKeyDown,
3374
+ children: items.map((entry, index) => {
3375
+ const ItemIcon = entry.icon;
3376
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
3377
+ "button",
3378
+ {
3379
+ type: "button",
3380
+ role: "menuitem",
3381
+ tabIndex: -1,
3382
+ className: entry.danger ? dangerItem : item3,
3383
+ "data-testid": slot(`item-${index}`),
3384
+ onClick: () => {
3385
+ entry.onClick?.();
3386
+ setOpen(false);
3387
+ },
3388
+ children: [
3389
+ ItemIcon ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ItemIcon, { size: ICON_SIZE4 }) : null,
3390
+ entry.label
3391
+ ]
3163
3392
  },
3164
- children: [
3165
- ItemIcon ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ItemIcon, { size: ICON_SIZE4 }) : null,
3166
- entry.label
3167
- ]
3168
- },
3169
- index
3170
- );
3171
- })
3172
- }
3173
- )
3393
+ index
3394
+ );
3395
+ })
3396
+ }
3397
+ ),
3398
+ document.body
3399
+ ) : null
3174
3400
  ]
3175
3401
  }
3176
3402
  );
3177
3403
  });
3178
3404
 
3179
3405
  // src/components/dialog/index.tsx
3180
- var import_react63 = require("react");
3181
- var import_react_dom = require("react-dom");
3406
+ var import_react64 = require("react");
3407
+ var import_react_dom3 = require("react-dom");
3182
3408
 
3183
3409
  // src/components/dialog/use-styles.ts
3184
- var import_react62 = require("react");
3410
+ var import_react63 = require("react");
3185
3411
 
3186
3412
  // src/components/dialog/use-styles.css.ts
3187
3413
  var actions = "use-styles_actions__5tstu83";
@@ -3192,7 +3418,7 @@ var surface2 = "use-styles_surface__5tstu81";
3192
3418
  // src/components/dialog/use-styles.ts
3193
3419
  function useStyles28() {
3194
3420
  const { themeClass } = useTheme();
3195
- return (0, import_react62.useMemo)(
3421
+ return (0, import_react63.useMemo)(
3196
3422
  () => ({
3197
3423
  overlay: [themeClass, overlay].filter(Boolean).join(" "),
3198
3424
  surface: surface2,
@@ -3206,22 +3432,22 @@ function useStyles28() {
3206
3432
  // src/components/dialog/index.tsx
3207
3433
  var import_jsx_runtime43 = require("react/jsx-runtime");
3208
3434
  var FOCUSABLE = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
3209
- function assignRef2(ref, value) {
3435
+ function assignRef3(ref, value) {
3210
3436
  if (typeof ref === "function") ref(value);
3211
3437
  else if (ref) ref.current = value;
3212
3438
  }
3213
- var Dialog = (0, import_react63.forwardRef)(function Dialog2({ open, onClose, title, actions: actions3, children, testId }, ref) {
3439
+ var Dialog = (0, import_react64.forwardRef)(function Dialog2({ open, onClose, title, actions: actions3, children, testId }, ref) {
3214
3440
  const { overlay: overlay2, surface: surface3, body: body3, actions: actionsClass } = useStyles28();
3215
3441
  const { testId: rootTestId, slot } = useTestId("dialog", testId);
3216
- const surfaceRef = (0, import_react63.useRef)(null);
3442
+ const surfaceRef = (0, import_react64.useRef)(null);
3217
3443
  const setSurfaceRef = (node) => {
3218
3444
  surfaceRef.current = node;
3219
- assignRef2(ref, node);
3445
+ assignRef3(ref, node);
3220
3446
  };
3221
- const previouslyFocused = (0, import_react63.useRef)(null);
3222
- const generatedId = (0, import_react63.useId)();
3447
+ const previouslyFocused = (0, import_react64.useRef)(null);
3448
+ const generatedId = (0, import_react64.useId)();
3223
3449
  const titleId = title != null ? generatedId : void 0;
3224
- (0, import_react63.useEffect)(() => {
3450
+ (0, import_react64.useEffect)(() => {
3225
3451
  if (!open) return;
3226
3452
  const onKeyDown = (event) => {
3227
3453
  if (event.key === "Escape") onClose();
@@ -3229,13 +3455,13 @@ var Dialog = (0, import_react63.forwardRef)(function Dialog2({ open, onClose, ti
3229
3455
  document.addEventListener("keydown", onKeyDown);
3230
3456
  return () => document.removeEventListener("keydown", onKeyDown);
3231
3457
  }, [open, onClose]);
3232
- (0, import_react63.useEffect)(() => {
3458
+ (0, import_react64.useEffect)(() => {
3233
3459
  if (!open) return;
3234
3460
  previouslyFocused.current = document.activeElement;
3235
3461
  surfaceRef.current?.focus();
3236
3462
  return () => previouslyFocused.current?.focus?.();
3237
3463
  }, [open]);
3238
- (0, import_react63.useEffect)(() => {
3464
+ (0, import_react64.useEffect)(() => {
3239
3465
  if (!open) return;
3240
3466
  const previousOverflow = document.body.style.overflow;
3241
3467
  document.body.style.overflow = "hidden";
@@ -3271,7 +3497,7 @@ var Dialog = (0, import_react63.forwardRef)(function Dialog2({ open, onClose, ti
3271
3497
  first.focus();
3272
3498
  }
3273
3499
  };
3274
- return (0, import_react_dom.createPortal)(
3500
+ return (0, import_react_dom3.createPortal)(
3275
3501
  // biome-ignore lint/a11y/useKeyWithClickEvents: ESC handled by a document keydown listener.
3276
3502
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: overlay2, "data-testid": slot("overlay"), onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
3277
3503
  "div",
@@ -3297,11 +3523,11 @@ var Dialog = (0, import_react63.forwardRef)(function Dialog2({ open, onClose, ti
3297
3523
  });
3298
3524
 
3299
3525
  // src/components/snackbar/index.tsx
3300
- var import_react65 = require("react");
3301
- var import_react_dom2 = require("react-dom");
3526
+ var import_react66 = require("react");
3527
+ var import_react_dom4 = require("react-dom");
3302
3528
 
3303
3529
  // src/components/snackbar/use-styles.ts
3304
- var import_react64 = require("react");
3530
+ var import_react65 = require("react");
3305
3531
 
3306
3532
  // src/components/snackbar/use-styles.css.ts
3307
3533
  var closeBtn = "use-styles_closeBtn__ihzsep2";
@@ -3311,7 +3537,7 @@ var root21 = "use-styles_root__ihzsep0 surfaces_inkySurface__1qa7atn2";
3311
3537
  // src/components/snackbar/use-styles.ts
3312
3538
  function useStyles29() {
3313
3539
  const { themeClass } = useTheme();
3314
- return (0, import_react64.useMemo)(
3540
+ return (0, import_react65.useMemo)(
3315
3541
  () => ({
3316
3542
  root: [themeClass, root21].filter(Boolean).join(" "),
3317
3543
  message,
@@ -3324,7 +3550,7 @@ function useStyles29() {
3324
3550
  // src/components/snackbar/index.tsx
3325
3551
  var import_jsx_runtime44 = require("react/jsx-runtime");
3326
3552
  var DEFAULT_DURATION = 5e3;
3327
- var Snackbar = (0, import_react65.forwardRef)(function Snackbar2({
3553
+ var Snackbar = (0, import_react66.forwardRef)(function Snackbar2({
3328
3554
  open,
3329
3555
  message: message2,
3330
3556
  action,
@@ -3339,19 +3565,19 @@ var Snackbar = (0, import_react65.forwardRef)(function Snackbar2({
3339
3565
  }, ref) {
3340
3566
  const { root: root25, message: messageClass, closeBtn: closeBtn2 } = useStyles29();
3341
3567
  const { testId: dataTestId, slot } = useTestId("feedback", testId);
3342
- const onCloseRef = (0, import_react65.useRef)(onClose);
3343
- (0, import_react65.useEffect)(() => {
3568
+ const onCloseRef = (0, import_react66.useRef)(onClose);
3569
+ (0, import_react66.useEffect)(() => {
3344
3570
  onCloseRef.current = onClose;
3345
3571
  }, [onClose]);
3346
- const interactingRef = (0, import_react65.useRef)({ hover: false, focus: false });
3347
- const timeoutRef = (0, import_react65.useRef)();
3348
- const clearTimer = (0, import_react65.useCallback)(() => {
3572
+ const interactingRef = (0, import_react66.useRef)({ hover: false, focus: false });
3573
+ const timeoutRef = (0, import_react66.useRef)();
3574
+ const clearTimer = (0, import_react66.useCallback)(() => {
3349
3575
  if (timeoutRef.current !== void 0) {
3350
3576
  clearTimeout(timeoutRef.current);
3351
3577
  timeoutRef.current = void 0;
3352
3578
  }
3353
3579
  }, []);
3354
- const scheduleTimer = (0, import_react65.useCallback)(() => {
3580
+ const scheduleTimer = (0, import_react66.useCallback)(() => {
3355
3581
  clearTimer();
3356
3582
  if (!open || duration == null || !onCloseRef.current) return;
3357
3583
  if (interactingRef.current.hover || interactingRef.current.focus) return;
@@ -3359,7 +3585,7 @@ var Snackbar = (0, import_react65.forwardRef)(function Snackbar2({
3359
3585
  onCloseRef.current?.();
3360
3586
  }, duration);
3361
3587
  }, [open, duration, clearTimer]);
3362
- (0, import_react65.useEffect)(() => {
3588
+ (0, import_react66.useEffect)(() => {
3363
3589
  scheduleTimer();
3364
3590
  return clearTimer;
3365
3591
  }, [scheduleTimer, clearTimer]);
@@ -3384,7 +3610,7 @@ var Snackbar = (0, import_react65.forwardRef)(function Snackbar2({
3384
3610
  onBlur?.(event);
3385
3611
  };
3386
3612
  if (!open || typeof document === "undefined") return null;
3387
- return (0, import_react_dom2.createPortal)(
3613
+ return (0, import_react_dom4.createPortal)(
3388
3614
  /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
3389
3615
  "div",
3390
3616
  {
@@ -3419,10 +3645,10 @@ var Snackbar = (0, import_react65.forwardRef)(function Snackbar2({
3419
3645
  });
3420
3646
 
3421
3647
  // src/components/table/index.tsx
3422
- var import_react67 = require("react");
3648
+ var import_react68 = require("react");
3423
3649
 
3424
3650
  // src/components/table/use-styles.ts
3425
- var import_react66 = require("react");
3651
+ var import_react67 = require("react");
3426
3652
 
3427
3653
  // src/components/table/use-styles.css.ts
3428
3654
  var alignRight = "use-styles_alignRight__1n2cz6i3";
@@ -3434,7 +3660,7 @@ var th = "use-styles_th__1n2cz6i1";
3434
3660
  // src/components/table/use-styles.ts
3435
3661
  function useStyles30({ className }) {
3436
3662
  const { themeClass } = useTheme();
3437
- const root25 = (0, import_react66.useMemo)(
3663
+ const root25 = (0, import_react67.useMemo)(
3438
3664
  () => [themeClass, root22, className].filter(Boolean).join(" "),
3439
3665
  [themeClass, className]
3440
3666
  );
@@ -3460,15 +3686,15 @@ function TableInner({ columns, rows, getRowKey, className, caption: caption2, te
3460
3686
  /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("tbody", { children: rows.map((row, index) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("tr", { "data-testid": slot(`row-${index}`), children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("td", { className: cellClass(column), children: column.render ? column.render(row) : String(row[column.key]) }, column.key)) }, getRowKey ? getRowKey(row, index) : index)) })
3461
3687
  ] });
3462
3688
  }
3463
- var TableForwarded = (0, import_react67.forwardRef)(TableInner);
3689
+ var TableForwarded = (0, import_react68.forwardRef)(TableInner);
3464
3690
  TableForwarded.displayName = "Table";
3465
3691
  var Table = TableForwarded;
3466
3692
 
3467
3693
  // src/components/app-bar/index.tsx
3468
- var import_react69 = require("react");
3694
+ var import_react70 = require("react");
3469
3695
 
3470
3696
  // src/components/app-bar/use-styles.ts
3471
- var import_react68 = require("react");
3697
+ var import_react69 = require("react");
3472
3698
 
3473
3699
  // src/components/app-bar/use-styles.css.ts
3474
3700
  var actions2 = "use-styles_actions__1h133nh2";
@@ -3478,7 +3704,7 @@ var root23 = "use-styles_root__1h133nh0";
3478
3704
  // src/components/app-bar/use-styles.ts
3479
3705
  function useStyles31({ className }) {
3480
3706
  const { themeClass } = useTheme();
3481
- const root25 = (0, import_react68.useMemo)(
3707
+ const root25 = (0, import_react69.useMemo)(
3482
3708
  () => [themeClass, root23, className].filter(Boolean).join(" "),
3483
3709
  [themeClass, className]
3484
3710
  );
@@ -3487,7 +3713,7 @@ function useStyles31({ className }) {
3487
3713
 
3488
3714
  // src/components/app-bar/index.tsx
3489
3715
  var import_jsx_runtime46 = require("react/jsx-runtime");
3490
- var AppBar = (0, import_react69.forwardRef)(function AppBar2({ brand: brand2, actions: actions3, className, children, testId, ...rest }, ref) {
3716
+ var AppBar = (0, import_react70.forwardRef)(function AppBar2({ brand: brand2, actions: actions3, className, children, testId, ...rest }, ref) {
3491
3717
  const styles = useStyles31({ className });
3492
3718
  const { testId: dataTestId, slot } = useTestId("nav", testId);
3493
3719
  return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("header", { ref, className: styles.root, "data-testid": dataTestId, ...rest, children: [
@@ -3498,10 +3724,10 @@ var AppBar = (0, import_react69.forwardRef)(function AppBar2({ brand: brand2, ac
3498
3724
  });
3499
3725
 
3500
3726
  // src/components/list-item/index.tsx
3501
- var import_react71 = require("react");
3727
+ var import_react72 = require("react");
3502
3728
 
3503
3729
  // src/components/list-item/use-styles.ts
3504
- var import_react70 = require("react");
3730
+ var import_react71 = require("react");
3505
3731
 
3506
3732
  // src/components/list-item/use-styles.css.ts
3507
3733
  var content3 = "use-styles_content__kbreq13";
@@ -3516,7 +3742,7 @@ function useStyles32({
3516
3742
  className
3517
3743
  }) {
3518
3744
  const { themeClass } = useTheme();
3519
- const root25 = (0, import_react70.useMemo)(
3745
+ const root25 = (0, import_react71.useMemo)(
3520
3746
  () => [themeClass, root24, selected4 && selected3, className].filter(Boolean).join(" "),
3521
3747
  [themeClass, selected4, className]
3522
3748
  );
@@ -3525,7 +3751,7 @@ function useStyles32({
3525
3751
 
3526
3752
  // src/components/list-item/index.tsx
3527
3753
  var import_jsx_runtime47 = require("react/jsx-runtime");
3528
- var ListItem = (0, import_react71.forwardRef)(function ListItem2({ leading: leading2, trailing: trailing2, selected: selected4, className, testId, children, ...rest }, ref) {
3754
+ var ListItem = (0, import_react72.forwardRef)(function ListItem2({ leading: leading2, trailing: trailing2, selected: selected4, className, testId, children, ...rest }, ref) {
3529
3755
  const styles = useStyles32({ selected: selected4, className });
3530
3756
  const { testId: dataTestId, slot } = useTestId("list", testId);
3531
3757
  return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(