@cosxai/ui 0.23.1 → 0.23.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosxai/ui",
3
- "version": "0.23.1",
3
+ "version": "0.23.3",
4
4
  "description": "COSX design system \u2014 React 19 component primitives shared across product-meta and other consumers",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -78,6 +78,13 @@ export function useKeyboardHotkey(
78
78
  if (skipWhenModalOpen && document.querySelector('[role="dialog"]')) {
79
79
  return;
80
80
  }
81
+ // The key is OURS once every guard passed — swallow its default
82
+ // action. Without this, a hotkey that opens a dialog with an
83
+ // autofocused input sees the same keystroke land as text ("s"
84
+ // typed into the invite search, meta QA 2026-08-19): the
85
+ // browser's text-insertion runs AFTER keydown, by which time
86
+ // focus has moved into the new input.
87
+ e.preventDefault();
81
88
  handlerRef.current(e);
82
89
  };
83
90
  window.addEventListener("keydown", onKey);
@@ -122,6 +122,10 @@ interface PopoverRect {
122
122
  top: number;
123
123
  left: number;
124
124
  width: number;
125
+ /** Set when the menu opens UPWARD (trigger near the viewport
126
+ * bottom): `top` is then the popover's bottom edge expressed as
127
+ * a CSS `bottom` inset. */
128
+ openUp: boolean;
125
129
  }
126
130
 
127
131
  export const Select = forwardRef<HTMLButtonElement, SelectProps>(function Select(
@@ -192,12 +196,20 @@ export const Select = forwardRef<HTMLButtonElement, SelectProps>(function Select
192
196
  const el = triggerRef.current;
193
197
  if (!el) return null;
194
198
  const r = el.getBoundingClientRect();
199
+ // Flip upward when the space below can't fit the menu but the
200
+ // space above can (QA 2026-08-20: the last options of a Select
201
+ // at the bottom of a drawer sat under the fixed action bar).
202
+ // Worst-case menu height; the listbox scrolls inside either way.
203
+ const needed = maxOptionsHeight + (searchable ? 48 : 0) + POPOVER_GAP;
204
+ const below = window.innerHeight - r.bottom;
205
+ const openUp = below < needed && r.top > below;
195
206
  return {
196
- top: r.bottom + POPOVER_GAP,
207
+ top: openUp ? window.innerHeight - r.top + POPOVER_GAP : r.bottom + POPOVER_GAP,
197
208
  left: r.left,
198
209
  width: r.width,
210
+ openUp,
199
211
  };
200
- }, []);
212
+ }, [maxOptionsHeight, searchable]);
201
213
 
202
214
  // Position the popover on open + on window resize. Close on
203
215
  // page scroll — keeps the popover from drifting off the trigger
@@ -487,7 +499,7 @@ export const Select = forwardRef<HTMLButtonElement, SelectProps>(function Select
487
499
  className="ck-select-popover"
488
500
  style={{
489
501
  position: "fixed",
490
- top: rect.top,
502
+ ...(rect.openUp ? { bottom: rect.top } : { top: rect.top }),
491
503
  left: rect.left,
492
504
  width: rect.width,
493
505
  zIndex: 1000,